Dengan tabel pembantu yang mendefinisikan batas "Utang" yang diterapkan pada tabel sumber dengan total berjalan yang dihitung, perpotongan dari setiap jumlah total yang berjalan dengan batas "Uang" dapat dihitung:
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)
Harap diperhatikan:SUM(...) Over (Order By ... Rows Unbounded Preceding)
dan IIF(...)
hanya tersedia di SQL Server 2012+. Hal yang sama dapat dilakukan pada SQL Server 2008 melalui sub-query meskipun kurang efisien:
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)