Solved

Balance Snapshot and Lag Window Function

Posted on 2013-06-18
2
210 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

Windows Server 2016: All you need to know

Learn about Hyper-V features that increase functionality and usability of Microsoft Windows Server 2016. Also, throughout this eBook, you’ll find some basic PowerShell examples that will help you leverage the scripts in your environments!

Question has a verified solution.

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

If you have heard of RFC822 date formats, they can be quite a challenge in SQL Server. RFC822 is an Internet standard format for email message headers, including all dates within those headers. The RFC822 protocols are available in detail at:   ht…
SQL Server engine let you use a Windows account or a SQL Server account to connect to a SQL Server instance. This can be configured immediatly during the SQL Server installation or after in the Server Authentication section in the Server properties …
Migrating to Microsoft Office 365 is becoming increasingly popular for organizations both large and small. If you have made the leap to Microsoft’s cloud platform, you know that you will need to create a corporate email signature for your Office 365…
This is used to tweak the memory usage for your computer, it is used for servers more so than workstations but just be careful editing registry settings as it may cause irreversible results. I hold no responsibility for anything you do to the regist…

920 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

Need Help in Real-Time?

Connect with top rated Experts

16 Experts available now in Live!

Get 1:1 Help Now