Quick window function solution, should be self explanatory
😎
USE tempdb;
GO
SET NOCOUNT ON;
IF OBJECT_ID('dbo.qamt') IS NOT NULL DROP TABLE dbo.qamt;
CREATE TABLE qamt(id INT, amt INT);
IF OBJECT_ID('dbo.qtot') IS NOT NULL DROP TABLE dbo.qtot;
CREATE TABLE dbo.qtot(id INT, tot INT);
INSERT INTO dbo.qamt
VALUES(1,10),
(1,20),
(1,30),
(2,90),
(2,10),
(3,150),
(4,20),
(4,40),
(4,50),
(4,70);
INSERT INTO dbo.qtot
VALUES(1,100),
(2,100),
(3,100),
(4,100);
;WITH ORDERED_TRANSACTION_SET AS
(
SELECT
QA.id
,ROW_NUMBER() OVER
(
ORDER BY (SELECT NULL)
) AS QA_RID
,QA.amt
FROM dbo.qamt QA
)
,RUNNING_TOTAL_SET AS
(
SELECT
QT.id
,QT.tot
,OTS.amt
,QT.tot - SUM(OTS.amt) OVER
(
PARTITION BY QT.id
ORDER BY OTS.QA_RID
ROWS BETWEEN UNBOUNDED PRECEDING
AND CURRENT ROW
) AS AC_BALANCE
FROM dbo.qtot QT
OUTER APPLY ORDERED_TRANSACTION_SET OTS
WHERE QT.id = OTS.id
)
SELECT
RTS.id
,RTS.tot
,RTS.amt
,CASE
WHEN RTS.AC_BALANCE >= 0 THEN RTS.AC_BALANCE
ELSE 0
END AS RTS_BALANCE
,RTS.AC_BALANCE
FROM RUNNING_TOTAL_SET RTS;
Results
id tot amt RTS_BALANCE AC_BALANCE
----------- ----------- ----------- ----------- -----------
1 100 10 90 90
1 100 20 70 70
1 100 30 40 40
2 100 90 10 10
2 100 10 0 0
3 100 150 0 -50
4 100 20 80 80
4 100 40 40 40
4 100 50 0 -10
4 100 70 0 -80