Với bảng trợ giúp xác định ranh giới "Đến hạn" được áp dụng trên bảng nguồn với tổng số tiền đang chạy được tính toán, giao của mỗi tổng số tiền đang chạy với ranh giới "Đến hạn" có thể được tính:
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)
Xin lưu ý:SUM(...) Over (Order By ... Rows Unbounded Preceding)
và IIF(...)
chỉ khả dụng trên SQL Server 2012+. Điều tương tự có thể được thực hiện trên SQL Server 2008 thông qua truy vấn phụ mặc dù kém hiệu quả hơn nhiều:
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)