Met een hulptabel die "Verschuldigde" grenzen definieert die zijn opgelegd over de brontabel met berekend lopend totaal, kan een snijpunt van elk lopend totaalbedrag met de "Verschuldigd" grenzen worden berekend:
With Receipt As ( --< Sample source table
Select * From (Values
('R1', 100),
('R2', 100),
('R3', 70),
('R4', 50),
('R5', 200)
) V (ReceiptNo, Amount)
), ReceiptWithTotal As ( --< Source table with Running Totals calculated
Select *,
SUM(Amount) Over (Order By ReceiptNo Rows Unbounded Preceding) - Amount As RunningTotalBefore,
SUM(Amount) Over (Order By ReceiptNo Rows Unbounded Preceding) As RunningTotalAfter
From Receipt
), Due As ( --< Helper table to define intervals (can be generated dynamically to cover any Total)
Select * From (Values
('D1', 0, 100),
('D2', 100, 200),
('D3', 200, 300),
('D4', 300, 400),
('D5', 400, 500),
('D6', 500, 600)
) V (DueNo, AmountLow, AmountHigh)
)
Select DueNo, ReceiptNo,
IIF(AmountHigh < RunningTotalAfter, AmountHigh, RunningTotalAfter) -
IIF(AmountLow > RunningTotalBefore, AmountLow, RunningTotalBefore) As Amount
From Due
Inner Join ReceiptWithTotal On NOT (RunningTotalAfter <= AmountLow OR RunningTotalBefore >= AmountHigh)
Let op:SUM(...) Over (Order By ... Rows Unbounded Preceding)
en IIF(...)
zijn alleen beschikbaar op SQL Server 2012+. Hetzelfde kan gedaan worden op SQL Server 2008 door middel van subquery's, hoewel veel minder efficiënt:
With Receipt As ( --< Sample source table
Select * From (Values
('R1', 100),
('R2', 100),
('R3', 70),
('R4', 50),
('R5', 200)
) V (ReceiptNo, Amount)
), ReceiptWithTotal As ( --< Source table with Running Totals calculated
Select *, RunningTotalAfter - Amount As RunningTotalBefore
From (
Select *,
(Select SUM(Amount) From Receipt B Where B.ReceiptNo <= A.ReceiptNo) As RunningTotalAfter
From Receipt A
) A
), Due As ( --< Helper table to define intervals (can be generated dynamically to cover any Total)
Select * From (Values
('D1', 0, 100),
('D2', 100, 200),
('D3', 200, 300),
('D4', 300, 400),
('D5', 400, 500),
('D6', 500, 600)
) V (DueNo, AmountLow, AmountHigh)
)
Select DueNo, ReceiptNo,
CASE WHEN AmountHigh < RunningTotalAfter THEN AmountHigh ELSE RunningTotalAfter END -
CASE WHEN AmountLow > RunningTotalBefore THEN AmountLow ELSE RunningTotalBefore END As Amount
From Due
Inner Join ReceiptWithTotal On NOT (RunningTotalAfter <= AmountLow OR RunningTotalBefore >= AmountHigh)