Create a Cumulative Sum Column in MySQL

Create a Cumulative Sum Column in MySQL

If performance is an issue, you could use a MySQL variable:

set @csum := 0;
update YourTable
set cumulative_sum = (@csum := @csum + count)
order by id;

Alternatively, you could remove the cumulative_sum column and calculate it on each query:

set @csum := 0;
select id, count, (@csum := @csum + count) as cumulative_sum
from YourTable
order by id;

This calculates the running sum in a running way :)

Creating a cumulative sum column in MySQL

I think I figured out the solution.

Select num as n, 
(select sum(num) from ID where num <= n)
from ID order by n;

Cumulative Sum in MySQL

You can achieve that in two steps: first of all get the sum for each year and month

select  concat(year(created_at), lpad(month(created_at), 2, '0')) as ye_mo,
count(*) as cnt
from users
group by concat(year(created_at), lpad(month(created_at), 2, '0'))

Then join it with itself, having each row matched with all previous ones

select  t1.ye_mo, sum(t2.cnt)
from (
select concat(year(created_at), lpad(month(created_at), 2, '0')) as ye_mo,
count(*) as cnt
from users
group by concat(year(created_at), lpad(month(created_at), 2, '0'))
) t1
join (
select concat(year(created_at), lpad(month(created_at), 2, '0')) as ye_mo,
count(*) as cnt
from users
group by concat(year(created_at), lpad(month(created_at), 2, '0'))
) t2
on t1.ye_mo >= t2.ye_mo
group by t1.ye_mo
order by t1.ye_mo

Edit

The query above assumes you want the running sum to increase across different years. If you want to display the months only, and aggregate the values of different years in the same month, you can change id this way

select  t1.mnt, sum(t2.cnt)
from (
select month(created_at) as mnt,
count(*) as cnt
from userss
group by month(created_at)
) t1
join (
select month(created_at) as mnt,
count(*) as cnt
from userss
group by month(created_at)
) t2
on t1.mnt >= t2.mnt
group by t1.mnt
order by t1.mnt

Finally, if you want the running sum to reset at the beginning of each year, you can do that like this

select  t1.yr, t1.mn, sum(t2.cnt)
from (
select year(created_at) as yr, month(created_at) as mn,
count(*) as cnt
from userss
group by year(created_at), month(created_at)
) t1
join (
select year(created_at) as yr, month(created_at) as mn,
count(*) as cnt
from userss
group by year(created_at), month(created_at)
) t2
on t1.yr = t2.yr and
t1.mn >= t2.mn
group by t1.yr, t1.mn
order by t1.yr, t1.mn

All three versions can be seen in action here

How to create a cumulative sum grouped by column

You can use correlated subqueries:

select t.*,
(select count(*)
from table_of_interest t2
where t2.update_at <= t.updated_at and t2.state_one = 1
) as cumulative_sum_one_1,
(select count(*)
from table_of_interest t2
where t2.update_at <= t.updated_at and t2.state_one = 2
) as cumulative_sum_two_2
from table_of_interest t;

MySQL: Cumulative sum of column A and column B into Column B

You can achieve SQL Server LAG functionalisty in order to get that cumulative sum:

select @lagDate := 0, @lagShop := 0, @diffLag := 0, @cumSum := 0;

select *,
case when @lagDate = Date and @lagShop = Shop then @cumSum := @cumSum + @diffLag else @cumSum := 0 end,
@diffLag := Diffabcxyz,
@lagDate := Date,
@lagShop := Shop
from tbl
order by shop, date, hour

Demo

UPDATE regarding comment:

Can you please tell me how can i get it to not do the cumulative count for the first 3 hours?

select @lagDate := 0, @lagShop := 0, @diffLag := 0, @cumSum := 0, @diffLagLag := 0;

select *,
case when @lagDate = Date and @lagShop = Shop then @cumSum := @cumSum + @diffLagLag else @cumSum := 0 end,
@diffLagLag := @diffLag,
@diffLag := Diffabcxyz,
@lagDate := Date,
@lagShop := Shop
from tbl
order by shop, date, hour

Another demo

ANOTHER UPDATE:

select @lagDate := 0, @lagShop := 0, @diffLag := 0, @cumSum := 0;

select *,
case when @lagDate = Date and @lagShop = Shop and Hour > 3 then @cumSum := @cumSum + @diffLag else @cumSum := 0 end,
@diffLag := Diffabcxyz,
@lagDate := Date,
@lagShop := Shop
from tbl
order by shop, date, hour

Yet another demo

Cumulative sum over groups on SQL 5.7

On MySQL 5.7, we can use a correlated subquery to find the rolling sum:

SELECT
id,
count,
(SELECT SUM(t2.count) FROM yourTable t2
WHERE t2.id = t1.id AND t2.num <= t1.num) cumulative_sum
FROM yourTable t1
ORDER BY
id,
num

On MySQL 8+, we can use SUM as an analytic function:

SELECT
id,
count,
SUM(count) OVER (PARTITION BY id ORDER BY num) cumulative_sum
FROM yourTable
ORDER BY
id,
num;

MYSQL query group by and cumulative sum for financial orderbook

I use mysql 5.7 (since this version is using by me). you want to sum cummulative from the result of amount on each price, so you should use SUBQUERY in order to aggregation

Try this:

    set @CumulativeSum := 0;
SELECT price, summ,
(@CumulativeSum:= @CumulativeSum + summ) as cumsum
FROM (SELECT SUM(amount) as Summ
FROM (SELECT * FROM orderbook) a
GROUP BY price
ORDER BY price) b

result

+-------+------+--------+
| price | summ | cumsum |
+-------+------+--------+
| 10 | 1.00 | 1.00 |
| 20 | 3.50 | 4.50 |
| 21 | 3.00 | 7.50 |
+-------+------+--------+

this is the fiddle https://dbfiddle.uk/?rdbms=mysql_5.7&fiddle=4f607e38a23f069829dfaa177a8bc3d3

Create a Cumulative Sum Column in MySQL Based On an ID

You can do this using below query

select t.plrID,t.rndID,t.pnt,sum(t1.pnt) 
from table t
join table t1
on t.plrID = t1.plrID
and t1.rndID<=t.rndID
group by plrID,rndID

Sum of previous rows in mysql

Frist, add a unique column to the table, Then you can use the same sql syntax that you found.

For example, Add the ID column(PRIMARY Key, auto increment)

+----+----------+------+
| ID | Time | AR |
+----+----------+------+
| 1 | 00:00:00 | 0.12 |
| 2 | 01:00:00 | 0.16 |
| 3 | 02:00:00 | 0.13 |
| 4 | 03:00:00 | 0.19 |
| 5 | 04:00:00 | 0.11 |
| 6 | 00:00:00 | 0.15 |
| 7 | 01:00:00 | 0.34 |
| 8 | 02:00:00 | 0.56 |
| 9 | 03:00:00 | 0.67 |
| 10 | 04:00:00 | 0.92 |
+----+----------+------+

the SQL:

set @arsum_1 := 0;
set @arsum_2 := 0;
set @arsum_3 := 0;

select t.Time, t.AR, ROUND(IFNULL(t1.A1, 0),2) as `1`, ROUND(IFNULL(t2.A2, 0), 2) as `2`, ROUND(IFNULL(t3.A3, 0),2) as `3` from time_sample t
natural left join (select ID, @arsum_1 := @arsum_1 + AR as A1 from time_sample where Time='01:00') as t1
natural left join (select ID, @arsum_2 := @arsum_2 + AR as A2 from time_sample where Time='02:00') as t2
natural left join (select ID, @arsum_3 := @arsum_3 + AR as A3 from time_sample where Time='03:00') as t3 order by t.Time;

output:

+----------+------+------+------+------+
| Time | AR | 1 | 2 | 3 |
+----------+------+------+------+------+
| 00:00:00 | 0.12 | 0.00 | 0.00 | 0.00 |
| 00:00:00 | 0.15 | 0.00 | 0.00 | 0.00 |
| 01:00:00 | 0.16 | 0.16 | 0.00 | 0.00 |
| 01:00:00 | 0.34 | 0.50 | 0.00 | 0.00 |
| 02:00:00 | 0.13 | 0.00 | 0.13 | 0.00 |
| 02:00:00 | 0.56 | 0.00 | 0.69 | 0.00 |
| 03:00:00 | 0.19 | 0.00 | 0.00 | 0.19 |
| 03:00:00 | 0.67 | 0.00 | 0.00 | 0.86 |
| 04:00:00 | 0.11 | 0.00 | 0.00 | 0.00 |
| 04:00:00 | 0.92 | 0.00 | 0.00 | 0.00 |
+----------+------+------+------+------+


Related Topics



Leave a reply



Submit