I have a voucher status history table as a type2 slowly changing dimension table I am trying to get the summary total value of each status by each month before a particular date. This is my schema and insert code:
CREATE TABLE #HDimVouchers(
[HVoucherKey] [bigint] IDENTITY(1,1) NOT NULL,
[Voucher_id] [bigint] NOT NULL,
[VoucherStatusKey] [int] NOT NULL,
[Voucher_amt] [decimal](18, 2) NULL,
[DateStatusStart] [date] NULL,
[DateStatusEnd] [date] NULL
)
--drop table #HDimVouchers
insert #HDimVouchers
values
(10,2,10.00,'2019-01-01','2019-02-15'),
(10,4,10.00,'2019-02-16',null),
(13,4,10.00,'2019-01-10',null),
(11,2,15.00,'2019-01-01',null),
(12,2,20.00,'2019-03-12','2019-03-12'),
(12,4,20.00,'2019-03-13',null),
(15,2,205.00,'2019-05-25','2020-04-24'),
(15,6,205.00,'2020-04-25',null),
(21,2,100.00,'2019-02-16',null)
I would like to get a summary to total value by year-month by voucherstatuskey something like the below:
[Year-Month] | [VoucherStatusKey] | [Amount] |
---|---|---|
201901 | 2 | 25 |
201901 | 4 | 10 |
201902 | 2 | 100 |
201902 | 4 | 10 |
201903 | 4 | 20 |
201905 | 2 | 205 |
201906 | 2 | 205 |
201907 | 2 | 205 |
201908 | 2 | 205 |
201909 | 2 | 205 |
201910 | 2 | 205 |
201911 | 2 | 205 |
201912 | 2 | 205 |
202001 | 2 | 205 |
202002 | 2 | 205 |
202003 | 2 | 205 |
I have had many attempts to get the data as above, but I am struggling to get the correct format and values. Below is something I have tried
SELECT convert(nvarchar(4),Year([DateStatusStart])) + RIGHT('00' + CONVERT(NVARCHAR(2), DATEPART(Month, [DateStatusStart])), 2)
,[VoucherStatusKey]
,SUM([Voucher_amt]) OVER (PARTITION BY Year([DateStatusStart]),Month([DateStatusStart]), [VoucherStatusKey] ORDER BY [DateStatusStart]) AS running_total
FROM #HDimVouchers where [DateStatusStart] < '2020-03-31';
Let me assume that you want the value at the end of the month. Then, you can take the following approach:
join
to bring in the appropriate value.For the first part, you could use a tally or calendar table if one is available. However a recursive CTE is also convenient:
with vdates as (
select voucher_id, eomonth(min(DateStatusStart)) as eom
from HDimVouchers
group by voucher_id
union all
select voucher_id, eomonth(dateadd(month, 1, eom))
from vdates
where eom < '2020-03-01'
)
select vd.*, hv.Voucher_amt
from vdates vd join
HDimVouchers hv
on hv.voucher_id = vd.voucher_id and
vd.eom >= hv.DateStatusStart and
(vd.eom <= hv.DateStatusEnd or hv.DateStatusEnd is null)
order by vd.eom, vd.voucher_id;
Here is a db<>fiddle.