SQL tricks
September 13, 2022
Calculate transactions rolling balance with max limit
One more case using CTE (common table expressions). Assume we have table of financial transactions like posted below, where Id is transaction identifier integer auto increment without gaps, Type is D for deposits and W for withdrawals
+====+======+========+ | Id | Type | Amount | +====+======+========+ | 1 | D | 300 | +----+------+--------+ | 2 | D | 400 | +----+------+--------+ | 3 | D | 500 | +----+------+--------+ | 4 | W | 300 | +----+------+--------+ | 5 | D | 200 | +----+------+--------+ | 6 | W | 500 | +----+------+--------+
We need to calculate balance after each transaction that not over 1000. We can not use here standard window functions because limitation the balance, so we going to solve the problem using CTE
WITH CTE AS ( -- get first transaction SELECT Id, Type, Amount, Amount AS Balance FROM Transactions WHERE Id = 1 UNION ALL -- get each next trancaction SELECT Transactions.Id, Transactions.Type, Transactions.Amount, -- check if balance not over limit CASE -- when over limit set max balance WHEN CASE WHEN Transactions.Type = 'D' THEN CTE.Balance + Transactions.Amount ELSE CTE.Balance - Transactions.Amount END > 1000 THEN 1000 -- other case calculate new balance value using previous and -- current transaction type and amount ELSE CASE WHEN Transactions.Type = 'D' THEN CTE.Balance + Transactions.Amount ELSE CTE.Balance - Transactions.Amount END END FROM Transactions JOIN CTE ON CTE.Id + 1 = Transactions.Id ) SELECT * FROM CTE;
Result: +====+======+========+=========+ | Id | Type | Amount | Balance | +====+======+========+=========+ | 1 | D | 300 | 300 | +----+------+--------+---------+ | 2 | D | 400 | 700 | +----+------+--------+---------+ | 3 | D | 500 | 1000 | <-- here balance limited by max +----+------+--------+---------+ | 4 | W | 300 | 700 | +----+------+--------+---------+ | 5 | D | 200 | 900 | +----+------+--------+---------+ | 6 | W | 500 | 400 | +----+------+--------+---------+