Straight SQL isn't designed for row-to-row calculations---they can be done, but they're seriously inefficient, e.g., given a chequebook-like table tbl( id int primary key,d date,value decimal(10,2), key(date) ), this query will return a running balance ...
select
d, value,
(select sum(value) as balance
from tbl as running
where running.d <= tbl.d
) as balance
from tbl
order by d;
... but at the cost of recomputing the running sum from the top for every row. On a big table, even with a date index, that'll be slow.
Originally cursors were designed to remedy the awkwardness and slowness of SQL with row-to-row computations, but cursors are much slower than straight SQL.
A user variable can sidestep these inefficiencies by maintaining the running total in memory. Initialise the variable, then adjust its value as desired in the appropriate SELECT expression:
SET @balancel=0;
SELECT d, value, @balance:=@balance+value AS RunningSum
FROM tbl
ORDER BY d;
This example tracks the running balance and how much money from the most recent deposit remains ...
If your platform does not permit multiple queries per connection, and if you can tolerate the O(N2) inefficiency, a self-join does the same job as an accumulating user variable ...
SELECT c.id, c.value, d.RunningSum
FROM tbl c
JOIN (
SELECT a.id, SUM(b.value) AS RunningSum
FROM tbl a
LEFT JOIN tbl b ON b.id <= a.id
GROUP BY a.id
) d USING (id);
Accumulating a sum and resetting it (ie subgrouping it) on another column value is a little harder ...
drop table if exists t;
create table t( id smallint primary key, a char(1), v int );
insert into t values(1,'a',10),(2,'b',20),(3,'b',30),(4,'c',40);
select x.a, x.v, sum(x.v) as cum
from t x
join t y on y.a = x.a and y.id <= x.id
group by x.id
order by x.a, x.id;
+------+------+------+
| a | v | cum |
+------+------+------+
| a | 10 | 10 |
| b | 20 | 20 |
| b | 30 | 60 |
| c | 40 | 40 |
+------+------+------+
Since MySQL 8.0.12 we can do row-to-row calculations with Common Table Expressions using any of the above algorithms; here is a running sum CTE using the Row_Number() function to generate a sequential row id and the join algorithm for accumulating a sum...
with recursive -- SO `X` CAN SELF-REFERENCE
y as ( -- SEQUENTIAL ROW ID FROM ROW_NUMBER()
select
d, value,
row_number() over(order by d) as rn
from tbl
),
x as ( -- CUMULATIVE SUM
select
d, rn, value,
value as balance
from y
where rn=1 -- FIRST 'SEED' ROW
union all
select
y.d, y.rn, y.value,
x.balance + y.value as balance
from x
join y on y.rn=x.rn+1 -- `X` WALKS ITSELF
)
select d, value, balance -- DISPLAY RESULT
from x
order by x.rn;