Solved

Balance Snapshot and Lag Window Function

Posted on 2013-06-18
2
224 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
  • 2
2 Comments
 
LVL 48

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 48

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

NFR key for Veeam Backup for Microsoft Office 365

Veeam is happy to provide a free NFR license (for 1 year, up to 10 users). This license allows for the non‑production use of Veeam Backup for Microsoft Office 365 in your home lab without any feature limitations.

Question has a verified solution.

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

Suggested Solutions

Occasionally there is a need to clean table columns, especially if you have inherited legacy data. There are obviously many ways to accomplish that, including elaborate UPDATE queries with anywhere from one to numerous REPLACE functions (even within…
Ever needed a SQL 2008 Database replicated/mirrored/log shipped on another server but you can't take the downtime inflicted by initial snapshot or disconnect while T-logs are restored or mirror applied? You can use SQL Server Initialize from Backup…
This video shows how to use Hyena, from SystemTools Software, to bulk import 100 user accounts from an external text file. View in 1080p for best video quality.
Exchange organizations may use the Journaling Agent of the Transport Service to archive messages going through Exchange. However, if the Transport Service is integrated with some email content management application (such as an antispam), the admini…

685 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