Предполагая, что ваши исходные данные находятся в структуре, которую вы изначально предоставили (то есть: это не результат другого запроса), это довольно простое преобразование с использованием таблицы дат и промежуточной суммы через упорядоченный sum
.
Если у вас уже есть таблица дат, вы можете удалить первые 2 cte
s в этом сценарии:
declare @t table(DateValue date,InputAmount decimal(8,2),OutputAmount decimal(8,2),ProdType nvarchar(1));
insert into @t values
('2018-01-10',256.35,null,'A')
,('2018-02-05',null, 35.00,'B')
,('2018-02-15', 65.30,null,'A')
,('2018-03-20',158.00,null,'B')
,('2018-04-02',null, 63.32,'B')
,('2018-05-12',null,128.12,'A')
,('2018-06-20',null, 7.35,'B')
;
-- Min date can just be min date in the source table, but the max date should be the month end of the max date in the source table0
declare @MinDate date = (select min(DateValue) from @t);
declare @MaxDate date = (select max(dateadd(day,-1,dateadd(month,datediff(month,0,DateValue)+1,0))) from @t);
with n(n) as (select * from (values(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) t(t)) -- Using a tally table, built a table of dates
,d(d) as (select top(select datediff(day,@MinDate,@MaxDate)+1) dateadd(day,row_number() over (order by (select null))-1,@MinDate) from n n1,n n2,n n3, n n4)
,m as (select p.ProdType -- Then join to the source data to create a date value for each posible day for each product type
,d.d
,dateadd(day,-1,dateadd(month,datediff(month,0,d)+1,0)) as m -- And calculate a running total using a windowed aggregate
,sum(isnull(t.InputAmount,0) - isnull(t.OutputAmount,0)) over (partition by p.ProdType order by d.d) as RunningTotal
from d
cross join (select distinct ProdType
from @t
) as p
left join @t as t
on d.d = t.DateValue
and p.ProdType = t.ProdType
)
select m
,ProdType
,RunningTotal as Balance
from m
where m = d
order by m.d
,m.ProdType;
Выход:
+-------------------------+----------+---------+
| m | ProdType | Balance |
+-------------------------+----------+---------+
| 2018-01-31 00:00:00.000 | A | 256.35 |
| 2018-01-31 00:00:00.000 | B | 0.00 |
| 2018-02-28 00:00:00.000 | A | 321.65 |
| 2018-02-28 00:00:00.000 | B | -35.00 |
| 2018-03-31 00:00:00.000 | A | 321.65 |
| 2018-03-31 00:00:00.000 | B | 123.00 |
| 2018-04-30 00:00:00.000 | A | 321.65 |
| 2018-04-30 00:00:00.000 | B | 59.68 |
| 2018-05-31 00:00:00.000 | A | 193.53 |
| 2018-05-31 00:00:00.000 | B | 59.68 |
| 2018-06-30 00:00:00.000 | A | 193.53 |
| 2018-06-30 00:00:00.000 | B | 52.33 |
+-------------------------+----------+---------+