Keeping in mind that data could be huge, the quirky update could have been the fastest. For that you can visit this great article by Mr. Jeff Moden. But I have approached it in two ways i.e.
DECLARE @table TABLE
(
GLNO INT
,LoanNo INT
,TRANSACDATE DATETIME
,WITHDRAWAMOUNT INT
,COLLECTIONAMOUNT INT
)
INSERT @table
(
[GLNO]
,[LoanNo]
,[TRANSACDATE]
,[WITHDRAWAMOUNT]
,[COLLECTIONAMOUNT]
)
SELECT 1170, 553, '20100401', 25000, NULL
UNION ALL SELECT 1170, 553 , '20100410', NULL, 5000
UNION ALL SELECT 1170 , 553 , '20100415', NULL, 5000
UNION ALL SELECT 1170 , 553, '20100420', NULL, 10000
-- RECURSIVE CTE SOLUTION
;WITH TransactionsCTE
AS (SELECT ROW_NUMBER() OVER ( PARTITION BY [GLNO], [LoanNo] ORDER BY [TRANSACDATE] )ROWNUM
, [GLNO]
, [LoanNo]
, [TRANSACDATE]
, SUM(ISNULL([WITHDRAWAMOUNT], 0)) [WITHDRAWAMOUNT]
, SUM(ISNULL([COLLECTIONAMOUNT], 0))[COLLECTIONAMOUNT]
, SUM(ISNULL([WITHDRAWAMOUNT], 0))
- SUM(ISNULL([COLLECTIONAMOUNT], 0)) TotalAmount
FROM @table AS T
GROUP BY [GLNO]
, [LoanNo]
, [TRANSACDATE]
)
, CalculationCTE
AS
(
SELECT *,TotalAmount AS RunningTotal
FROM TransactionsCTE WHERE ROWNUM = 1
UNION ALL
SELECT C.*, C.TotalAmount + T.RunningTotal
FROM [TransactionsCTE] AS C
INNER JOIN CalculationCTE AS T ON C.[GLNO] = T.[GLNO]
AND C.[LoanNo] = T.[LoanNo]
AND C.[ROWNUM] = T.[ROWNUM] + 1
WHERE C.ROWNUM > 1
)
SELECT [C].[GLNO]
, [C].[LoanNo]
, [C].[TRANSACDATE] WithDrawDate
, [C].[RunningTotal] [WITHDRAWAMOUNT]
, [T].[TRANSACDATE] CollectionDate
, [T].[COLLECTIONAMOUNT]
, [T].[RunningTotal] Balance
FROM CalculationCTE C
INNER JOIN [CalculationCTE] T ON C.[GLNO] = T.[GLNO]
AND C.[LoanNo] = T.[LoanNo]
AND T.[ROWNUM] = C.[ROWNUM] + 1
CREATE TABLE #Output
(
ROWNUM INT
,GLNO INT
,LoanNo INT
,TRANSACDATE DATETIME NOT NULL
,WITHDRAWAMOUNT INT
,COLLECTIONAMOUNT INT
,WithDrawAmountCalc INT
,PRIMARY KEY ( ROWNUM, GLNO, LoanNo )
)
INSERT [#Output]
(
[ROWNUM]
,[GLNO]
,[LoanNo]
,[TRANSACDATE]
,[WITHDRAWAMOUNT]
,[COLLECTIONAMOUNT]
,[WithDrawAmountCalc]
)
SELECT ROW_NUMBER() OVER ( PARTITION BY [GLNO], [LoanNo] ORDER BY [TRANSACDATE] )
, [GLNO]
, [LoanNo]
, [TRANSACDATE]
, SUM(ISNULL([WITHDRAWAMOUNT], 0))
, SUM(ISNULL([COLLECTIONAMOUNT], 0))
, SUM(ISNULL([WITHDRAWAMOUNT], 0))
- SUM(ISNULL([COLLECTIONAMOUNT], 0))
FROM @table AS T
GROUP BY [GLNO]
, [LoanNo]
, [TRANSACDATE]
DECLARE @RowNum INT
, @RowCount INT ;
SELECT @RowNum = 1
, @RowCount = 1 ;
WHILE @RowCount > 0
BEGIN;
SET @RowNum = @RowNum + 1 ;
UPDATE nxt
SET [WithDrawAmountCalc] = prv.[WithDrawAmountCalc]
+ ( [nxt].[WITHDRAWAMOUNT] - [nxt].[COLLECTIONAMOUNT] )
FROM #Output AS nxt
INNER JOIN #Output AS prv
ON prv.[GLNO] = nxt.[GLNO]
AND [nxt].[LoanNo] = [prv].[LoanNo]
AND prv.RowNum = @RowNum - 1
WHERE nxt.RowNum = @RowNum ;
SET @RowCount = @@ROWCOUNT ;
END ;
SELECT [GLNO]
, [LoanNo]
, [O].[TRANSACDATE] WithDrawDate
, [O].[WithDrawAmountCalc] [WITHDRAWAMOUNT]
, [A].[TRANSACDATE] CollectionDate
, [A].[COLLECTIONAMOUNT]
, [A].[WithDrawAmountCalc] Balance
FROM [#Output] AS O
CROSS APPLY ( SELECT [TRANSACDATE]
, [WithDrawAmountCalc]
, [COLLECTIONAMOUNT]
FROM [#Output] AS O2
WHERE [O].[GLNO] = [O2].[GLNO]
AND [O].[LoanNo] = [O2].[LoanNo]
AND [O2].[ROWNUM] = [O].[ROWNUM] + 1
) A
DROP TABLE [#Output]
Hope it helps.
P.S. Sorry but due to the time constraints I was not able to add the comments in the code.
4 People are following this question.