I would like a cumulative DR or CR balance for the following table:
+-----------+--------------+---------------+---------+ | id | Date | DR | CR | +-----------+--------------+---------------+---------+ | 1 | 2020-01-01 | 100 | 0 | | 2 | 2020-01-01 | 200 | 0 | | 3 | 2020-01-02 | 0 | 200 | | 4 | 2020-01-02 | 0 | 50 | | 5 | 2020-01-03 | 20 | 0 | +-----------+--------------+---------------+---------+
For the above table, a cumulative Balance column would be:
+-----------+--------------+---------------+---------+----------+ | id | Date | DR | CR | Balance | +-----------+--------------+---------------+---------+----------+ | 1 | 2020-01-01 | 100 | 0 | 100 DR | | 2 | 2020-01-01 | 200 | 0 | 300 DR | | 3 | 2020-01-02 | 0 | 300 | 0 DR | | 4 | 2020-01-02 | 0 | 50 | 50 CR | | 5 | 2020-01-03 | 20 | 0 | 30 CR | +-----------+--------------+---------------+---------+----------+
Decreasing a DR below 0 makes it a CR
Decreasing a CR below 0 makes it a DR
Where balance is 0, value is 0 DR
It could be calculated as CR’s being a negative value, but I would like the ‘DR’ and ‘CR’ text to show in the balance column after an abs numerical value.
mysql Ver 14.14 Distrib 5.7.23, for Linux (x86_64) using EditLine wrapper
Thanks for your help
Advertisement
Answer
If you are running MySQL 8.0, you can use window functions:
select
t.*,
concat(
abs(sum(dr - cr) over(order by date, id)),
' ',
case when sum(dr - cr) over(order by date, id) >= 0 then 'DR' else 'CR' end
) balance
from mytable t
In earlier versions, one efficient option uses a session variable:
set @sm = 0;
select id, date, dr, cr, concat(abs(bal), ' ', case when bal >= 0 then 'DR' else 'CR' end) balance
from (
select
t.*,
@sm := @sm + dr - cr bal
from (select t.* from mytable t order by date, id) t
) t
Demo on DB Fiddle – both queries yield:
| id | date | dr | cr | balance | | --- | ---------- | --- | --- | ------- | | 1 | 2020-01-01 | 100 | 0 | 100 DR | | 2 | 2020-01-01 | 200 | 0 | 300 DR | | 3 | 2020-01-02 | 0 | 300 | 0 DR | | 4 | 2020-01-02 | 0 | 50 | 50 CR | | 5 | 2020-01-03 | 20 | 0 | 30 CR |