Вам необходимо использовать SUM OVER()
для получения кумулятивного итога, см. Ниже рабочий код вашего кода:
DECLARE @testDuration TABLE (CustID INT, Duration decimal (18,0))
INSERT INTO @testDuration(CustID, Duration)
VALUES
(14005, 65)
, (14005, 200)
, (14005, 4800)
, (14005, 25)
, (14005, 5)
, (14005, 450)
, (14005, 21)
, (14005, 32)
, (14005, 335)
, (14005, 45)
, (14005, 9000)
, (14005, 250000);
if object_id('tempdb..#callRecords') is not null
drop table #callRecords;
select td.CustID, Duration,4250.2 as FrAvailableMinutes
into #callRecords
from @testDuration as td;
with cte as (
select cr.CustID
, cr.Duration
, cr.FrAvailableMinutes
, row_number() over (partition by cr.CustID order by duration asc) as CallDateKey
from #callRecords as cr
)
select cte.CustID
, cte.Duration
, cte.FrAvailableMinutes
, cte.CallDateKey
, round(sum(Duration) over (order by CallDateKey rows between unbounded preceding and current row)/60,2) as CumulativeDUration
, cte.FrAvailableMinutes - round(sum(Duration) over (order by CallDateKey rows between unbounded preceding and current row)/60,2) as MinutesLeft
from cte
order by CallDateKey desc
Редактировать: В дополнение к вашему комментарию ниже, у меня естьтакже предоставил решение по петле для вашего бизнеса:
declare @testDuration table
(
CustID int
, Duration decimal(18, 0)
, CallDateKey int
);
insert into @testDuration
(
CustID
, Duration
, CallDateKey
)
values
(14005, 65, 1)
, (14005, 200, 2)
, (14005, 4800, 3)
, (14005, 25, 4)
, (14005, 5, 5)
, (14005, 450, 6)
, (14005, 21, 7)
, (14005, 32, 8)
, (14005, 335, 9)
, (14005, 45, 10)
, (14005, 9000, 11)
, (14005, 250000, 12)
, (14005, 500, 13);
if object_id('tempdb..#Billing') is not null
drop table #Billing;
create table #Billing
(
CustId int
, Duration decimal(18, 0)
, FrAvailableSeconds decimal(18, 2)
, CallDateKey int
, CumulativeDuration decimal(18, 2)
, SecondsLeft decimal(18, 2)
);
with CallRecords
(CustID, DUration, CallDateKey, FrAvailableSeconds)
as (
select td.CustID
, Duration
, td.CallDateKey
, 4250.20 * 60
from @testDuration as td
)
insert into #Billing
(
CustId
, Duration
, FrAvailableSeconds
, CallDateKey
, CumulativeDuration
, SecondsLeft
)
select cr.CustID
, cr.DUration
, cr.FrAvailableSeconds
, cr.CallDateKey
, round( sum(DUration) over (order by
CallDateKey
rows between unbounded preceding and current row
) / 60
, 2
)
, cr.FrAvailableSeconds
from CallRecords as cr;
declare @a int = (
select min(CustId) from #Billing as b
);
declare @b int = (
select max(CustId) from #Billing as b
);
declare @x int;
declare @y int;
while @a <= @b
begin
set @x = (
select min(b.CallDateKey) from #Billing as b where b.CustId = @a
);
set @y = (
select max(b.CallDateKey) from #Billing as b where b.CustId = @a
);
while @x <= @y
begin
update b
set b.SecondsLeft = case
when isnull(ps.SecondsLeft, b.FrAvailableSeconds) - b.Duration < 0 then
isnull(ps.SecondsLeft, b.FrAvailableSeconds)
else
isnull(ps.SecondsLeft, b.FrAvailableSeconds) - b.Duration
end
from #Billing as b
left join (
select b.CustId
, SecondsLeft
from #Billing as b
where
b.CallDateKey = @x - 1
and b.CustId = @a
) as ps
on b.CustId = ps.CustId
where
b.CustId = @a
and b.CallDateKey = @x;
set @x += 1;
end;
set @a += 1;
end;
select b.CustId
, b.Duration
, b.FrAvailableSeconds
, b.FrAvailableSeconds / 60 as FrAvailableMinutes
, b.CallDateKey
, b.CumulativeDuration
, b.SecondsLeft
, b.SecondsLeft / 60 as MinutesLeft
from #Billing as b
order by
b.CallDateKey desc;