Solved

Balance Snapshot and Lag Window Function

Posted on 2013-06-18
2
239 Views
Last Modified: 2014-04-01
Having read the books - I understand that a daily snapshot should - by definition - be taken every day.  I am in the specialty credit card space.  Ours is not a daily use card.  Typically - our card is used only once or twice per month.

So I can't give it up.  I don't want to insert 31 rows where only a small number of changes have occurred.  I want to implement the snapshot as a view.  I would insert into a FactChange table only when a change in balance is observed.


For the below example uses cross join, left outer join and lag to accomplish ALMOST exactly what I want - a 20 row result set addressing 2 accounts over 10 days.  The lag gets the previous value and I can coalesce for the FIRST day of inactivity.  It fails on the second, third, yada yada because the previous day as null.

What I need is lag(c.Balance, LastNonNull)  That LastNonNull is the part I can't get my head around.  Can anyone help??


create table DimDate
(
    DateKey                  int not null,
    constraint PK_Date primary key clustered (DateKey)
);
go

insert into DimDate values
(20130601),
(20130602),
(20130603),
(20130604),
(20130605),
(20130606),
(20130607), 
(20130608),
(20130609),
(20130610);
go

create table DimAccount
(
    AccountKey                  int not null,
    constraint PK_Account primary key clustered (AccountKey)
);
go

insert into DimAccount values
(1),
(2);
go

create table FactBalanceChange
(
    DateKey                  int not null,
    AccountKey               int not null,
    Balance                  money not null,
    constraint PK_BalanceChange primary key clustered (DateKey, AccountKey),
    constraint FK_BalanceChange_DateKey foreign key (DateKey) references DimDate(DateKey),
    constraint FK_BalanceChange_AccountKey foreign key (AccountKey) references DimAccount(AccountKey)
);
go

insert into FactBalanceChange values
(20130601, 1, 10.00),
(20130601, 2, 10.00),
(20130604, 1, 5.00),
(20130607, 2, 5.00),
(20130609, 1, 4.00),
(20130609, 2, 4.00);
go

create view FactBalanceSnapshot as

    select 
        d.DateKey, 
        a.AccountKey, 
        coalesce(c.Balance, lag(c.Balance, 1) over (partition by a.AccountKey order by d.DateKey)) as Balance
    from 
            DimDate d
        cross join 
            DimAccount a
        left outer join
            FactBalanceChange c
                on d.DateKey = c.DateKey
               and a.AccountKey = c.AccountKey;  
go 


select * from FactBalanceSnapshot.
 

Open in new window

0
Comment
Question by:jflanner
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 2
2 Comments
 
LVL 49

Expert Comment

by:PortletPaul
ID: 39258305
does this help your thinking? Here I've placed the lag() function into a subquery on FactBalanceChange which avoids the issue of non-matching dates I believe.

I've left the query as displaying 2 columns so you may 'see' what's going on
--create view FactBalanceSnapshot as

    select 
          d.DateKey
        , a.AccountKey
        --, coalesce(c.Balance, lag(c.Balance, 1) over (partition by a.AccountKey order by d.DateKey)) as Balance
        , c.balance
        , c.lag_balance
    from 
            DimDate d
        cross join 
            DimAccount a
        left outer join (
                        select
                          fbc.dateKey
                        , fbc.AccountKey
                        , fbc.Balance
                        , lag(fbc.Balance, 1) over (partition by fbc.AccountKey order by fbc.DateKey ASC)
                            as lag_balance
                        from FactBalanceChange as fbc
                        ) as c
                on d.DateKey = c.DateKey
               and a.AccountKey = c.AccountKey;  
;

Open in new window

thanks for the tables and data - very helpful.
you can play with that data and this query at: http://sqlfiddle.com/#!6/8a56a/5
0
 
LVL 49

Accepted Solution

by:
PortletPaul earned 500 total points
ID: 39258921
on reflection I think the above comment isn't going to help - sorry, so back to questions I'm afraid. A 'running sum' (column 4) can be added quite simply - but I think you are after column 5 - can you confirm if this is the expected result please?
DATEKEY	ACCOUNTKEY	BALANCE	RUNSUM	Required?
20130601	1	10	10	10
20130602	1	(null)	10	10
20130603	1	(null)	10	10
20130604	1	5	15	5
20130605	1	(null)	15	5
20130606	1	(null)	15	5
20130607	1	(null)	15	5
20130608	1	(null)	15	5
20130609	1	4	19	4
20130610	1	(null)	19	4
				
20130601	2	10	10	10
20130602	2	(null)	10	10
20130603	2	(null)	10	10
20130604	2	(null)	10	10
20130605	2	(null)	10	10
20130606	2	(null)	10	10
20130607	2	5	15	5
20130608	2	(null)	15	5
20130609	2	4	19	4
20130610	2	(null)	19	4

Open in new window

runsum is produced by:
    select 
         d.DateKey 
       , a.AccountKey 
       , c.Balance
       , SUM(c.balance)over (partition by a.AccountKey order by d.DateKey) runsum
    from 
            DimDate d
        cross join 
            DimAccount a
        left outer join
            FactBalanceChange c
                on d.DateKey = c.DateKey
               and a.AccountKey = c.AccountKey

Open in new window

http://sqlfiddle.com/#!6/8a56a/19
0

Featured Post

Microsoft Certification Exam 74-409

Veeam® is happy to provide the Microsoft community with a study guide prepared by MVP and MCT, Orin Thomas. This guide will take you through each of the exam objectives, helping you to prepare for and pass the examination.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Hi all, It is important and often overlooked to understand “Database properties”. Often we see questions about "log files" or "where is the database" and one of the easiest ways to get general information about your database is to use “Database p…
Use this article to create a batch file to backup a Microsoft SQL Server database to a Windows folder.  The folder can be on the local hard drive or on a network share.  This batch file will query the SQL server to get the current date & time and wi…
In this video we outline the Physical Segments view of NetCrunch network monitor. By following this brief how-to video, you will be able to learn how NetCrunch visualizes your network, how granular is the information collected, as well as where to f…
In this video you will find out how to export Office 365 mailboxes using the built in eDiscovery tool. Bear in mind that although this method might be useful in some cases, using PST files as Office 365 backup is troublesome in a long run (more on t…

632 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question