Using a correlated query:


  SELECT t.id,
         t.count,
         (SELECT SUM(x.count)
            FROM TABLE x
           WHERE x.id <= t.id) AS cumulative_sum
    FROM TABLE t
ORDER BY t.id

Using MySQL variables:


  SELECT t.id,
         t.count,
         @running_total := @running_total + t.count AS cumulative_sum
    FROM TABLE t
    JOIN (SELECT @running_total := 0) r
ORDER BY t.id

Note:

  • The JOIN (SELECT @running_total := 0) r is a cross join, and allows for variable declaration without requiring a separate SET command.
  • The table alias, r, is required by MySQL for any subquery/derived table/inline view

Caveats:

  • MySQL specific; not portable to other databases
  • The ORDER BY is important; it ensures the order matches the OP and can have larger implications for more complicated variable usage (IE: psuedo ROW_NUMBER/RANK functionality, which MySQL lacks)
Answer from OMG Ponies on Stack Overflow
🌐
PopSQL
popsql.com › learn-sql › mysql › how-to-calculate-cumulative-sum-running-total-in-mysql
How to Calculate Cumulative Sum-Running Total in MySQL - PopSQL
Before MySQL version 8 you can use variables for this: SELECT t.day, t.rental_count, @running_total:=@running_total + t.rental_count AS cumulative_sum FROM ( SELECT date(rental_date) as day, count(rental_id) as rental_count FROM rental GROUP BY day ) t JOIN (SELECT @running_total:=0) r ORDER BY t.day; day | rental_count | cumulative_sum -----------+--------------+---------------- 2005-05-24 | 8 | 8 2005-05-25 | 137 | 145 2005-05-26 | 174 | 319 2005-05-27 | 166 | 485 2005-05-28 | 196 | 681
Discussions

mysql - Creating a cumulative totals column - Database Administrators Stack Exchange
SELECT SUM(SaleTotal) AS ... ) / SUM(DriverTotal)) * 100) AS Markup FROM TableA Order BY CollectionDate · I want to to create another similar query which returns a monthly cumulative result for Total cost, Total Sale Price & Profit ... Please consider following these suggestions. ... MySQL 8.0 is needed ... More on dba.stackexchange.com
🌐 dba.stackexchange.com
sql - Cumulative sum over a set of rows in mysql - Stack Overflow
I have a complex query(containing multiple joins, unions) that returns a set of rows containing id, day, hr, amount. The output of the query looks like this: id day hr amount 1 1 1 1... More on stackoverflow.com
🌐 stackoverflow.com
Cumulative sum or running sum
I think for it to be a running Sum you need ORDER BY in your parenthesis. SUM(COLUMN) OVER (ORDER BY productid) More on reddit.com
🌐 r/SQL
11
5
March 10, 2023
sql - Creating a cumulative sum column in MySQL - Stack Overflow
Sample table ID: (num is a key so there wouldn't be any duplicates) num 1 5 6 8 2 3 Desired output: (Should be sorted and have a cumulative sum column) num cumulative 1 1 2 3 3 6 5 11... More on stackoverflow.com
🌐 stackoverflow.com
🌐
TutorialsPoint
tutorialspoint.com › how-to-create-a-cumulative-sum-column-in-mysql
How to create a Cumulative Sum Column in MySQL?
mysql> select BookId,BookPrice,(@CumulativeSum := @CumulativeSum + BookPrice) as CumSum −> from CumulativeSumDemo order by BookId; The following is the output. Here the cumulative sum column is also visible −
🌐
GeeksforGeeks
geeksforgeeks.org › mysql › how-to-compute-a-running-total-in-mysql
How to Compute a Running Total in MySQL - GeeksforGeeks
July 23, 2025 - Explanation: The output displays the id and value columns from the your_table table, along with a running_total column. The running_total column shows the cumulative sum of value, calculated incrementally by row.
🌐
GitHub
gist.github.com › MagePsycho › 431233c15e1e0d1532376dcc1b8102f0
MySQL: Running Total (Cumulative Sum) · GitHub
MySQL: Running Total (Cumulative Sum). GitHub Gist: instantly share code, notes, and snippets.
🌐
Dbrnd
dbrnd.com › 2016 › 03 › mysql-how-to-generate-cumulative-sum-column
MySQL: How to generate Cumulative Sum Column? - dbrnd
October 9, 2017 - Database Research & Development: Full demonstration to calculate cumulative SUM column for a Table of MySQL Server.
🌐
Interview Query
interviewquery.com › p › sql-cumulative-sum-guide
SQL Cumulative SUM: Window Functions, Rolling Totals & Best Practices
March 17, 2026 - Not every SQL engine implements cumulative sums the same way. Most modern platforms follow the ANSI SQL window function standard (SUM() OVER (ORDER BY …)), while older versions or certain vendors require dialect-specific workarounds. The table below compares the syntax and highlights the nuances for MySQL (plus a MySQL 5.7 workaround), PostgreSQL, SQL Server, Oracle, SQLite, Snowflake, and Databricks/Spark.
Find elsewhere
🌐
OneUptime
oneuptime.com › home › blog › how to calculate cumulative sums in mysql
How to Calculate Cumulative Sums in MySQL
March 31, 2026 - SELECT month_start, region, revenue, SUM(revenue) OVER ( PARTITION BY region ORDER BY month_start ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ) AS cumulative_revenue FROM monthly_revenue ORDER BY region, month_start;
🌐
Datareportive
datareportive.com › tutorial › mysql › how-to-calculate-cumulative-sum-running-total
How to Calculate Cumulative Sum-Running Total in MySQL | DataReportive Tutorials
The ORDER BY sale_date ensures that the rows are processed in chronological order, and the SUM() function computes the cumulative sum of sale_amount. Before window functions were available in MySQL, one way to calculate a running total was by using session variables.
🌐
Coffingdw
coffingdw.com › mysql-analytics-cumulative-sum
MySQL Analytics – Cumulative Sum – Software connecting all databases
If you took a calculator and added up all of the daily_sales values you see below, you would find that the sum of these values is 442,962.75. The query below sorts the dataset rows by product_id (major sort) and sale_date (minor sort) and then adds up the daily_sales from the first row to the last. I want you to focus on the importance of the ORDER BY statement, which is ORDER BY product_id and then sale_date. Once the data is ordered, the cumulative sum adds up the daily_sales from the first row to the last.
🌐
LabEx
labex.io › tutorials › mysql-how-to-calculate-cumulative-totals-in-mysql-418610
How to calculate cumulative totals in MySQL | LabEx
-- Create a sample sales table ... 75.25); -- Basic cumulative total calculation SELECT sale_date, amount, SUM(amount) OVER (ORDER BY sale_date) AS cumulative_total FROM sales; ... By understanding these basics, database ...
🌐
Stack Exchange
dba.stackexchange.com › questions › 328693 › creating-a-cumulative-totals-column
mysql - Creating a cumulative totals column - Database Administrators Stack Exchange
SELECT MONTHNAME(LAST_DAY(CollectionDate)) AS Month, SUM(SaleTotal) AS TotalSalePrice, SUM(CostTotal) AS TotalPurchaseCost, SUM(Profit) AS Profit, (SUM(Profit) / SUM(DriverTotal)) * 100 AS Markup, SUM(SUM(SaleTotal)) OVER (ORDER BY LAST_DAY(CollectionDate) ROWS UNBOUNDED PRECEDING) AS CumulativeSalesPrice SUM(SUM(Profit)) OVER (ORDER BY LAST_DAY(CollectionDate) ROWS UNBOUNDED PRECEDING) AS CumulativeProfit FROM TableA GROUP BY LAST_DAY(CollectionDate) ORDER BY LAST_DAY(CollectionDate); Note the use of a proper grouping construct. Do not rely on MySQL's idiosyncratic method of displaying columsn which are not in the GROUP BY.
Top answer
1 of 3
13

UPDATE

MySQL 8.0 introduces "window functions", functionality equivalent to SQL Server "window functions" (with partitioning and ordering provided by Transact-SQL OVER syntax), and Oracle "analytic functions". It also now supports CTEs.

MySQL Reference Manual 12.21 Window Functions https://dev.mysql.com/doc/refman/8.0/en/window-functions.html

The answer provided here is an approach for MySQL versions prior to 8.0.


ORIGINAL ANSWER

MySQL doesn't provide the type analytic function you would use to get a running "cumulative sum", like the analytic functions available in other DBMS (like Oracle or SQL Server.)

But, it is possible to emulate some analytic functions, using MySQL.

There are (at least) two workable approaches:

One is to use a correlated subquery to get the subtotal. This approach can be expensive on large sets, and complicated if the predicates on the outer query are complicated. It really depends on how complicated that "multiple joins on multiple tables" is. (Unfortunately, MySQL also does not not support CTEs either.)

The other approach is to make use of MySQL user variables, to do some control break processing. The "trick" here is to the results from your query sorted (using an ORDER BY) and then wrapping your query in another query.

I'll give an example of the latter approach.

Because of the order that MySQL performs operations, the cumulative_total column needs to be computed before the value from id and day from the current row are saved into user variables. It's just easiest to put this column first.

The inline view aliased as i (in the query below) is just there to initialize the user variables, just in case these are already set in the session. If those already have values assigned, we want to ignore their current values, and the easiest way to do that is to initialize them.

Your original query gets wrapped in parenthesis, and is given an alias, c in the example below. The only change to your original query is the addition of an ORDER BY clause, so we can be sure that we process the rows from the query in sequence.

The outer select checks whether the id and day value from the current row "match" the previous row. If they do, we add the amount from the current row to the cumulative subtotal. If they don't match, then we reset the the cumulative subtotal to zero, and add the amount from the current row (or, more simply, just assign the amount from the current row).

After we have done the computation of the cumulative total, we save the id and day values from the current row into user variables, so they are available when we process the next row.

For example:

SELECT IF(@prev_id = c.id AND @prev_day = c.day
         ,@cumtotal := @cumtotal + c.amount
         ,@cumtotal := c.amount) AS cumulative_total
     , @prev_id  := c.id  AS `id`
     , @prev_day := c.day AS `day`
     , c.hr
     , c.amount AS `amount'
  FROM ( SELECT @prev_id  := NULL
              , @prev_day := NULL
              , @subtotal := 0
       ) i
  JOIN (

         select id, day, hr, amount from
         ( //multiple joins on multiple tables)a
         left join
         (//unions on multiple tables)b
         on a.id=b.id

         ORDER BY 1,2,3
       ) c

If it's necessary to return the columns in a different order, with cumulative total as the last column, then one option is to wrap that whole statement in a set of parens, and use that query as an inline view:

SELECT d.id
     , d.day
     , d.hr
     , d.amount
     , d.cumulative_total
FROM (
       // query from above
     ) d
2 of 3
7

If you're on MySQL 8 or later, you should use window functions for this. Your query would read:

SELECT
  id, day, hr, amount,
  SUM (amount) OVER (PARTITION BY id, day ORDER BY hr) AS `cumulative total`
FROM t

Where t is your table b left joined to a. Some notes:

  • The PARTITION BY clause guarantees that you get a cumulative sum per id and day, so each day, we start summing afresh
  • The ORDER BY clause defines by what ordering the cumulation should happen
🌐
CastorDoc
castordoc.com › how-to › how-to-calculate-cumulative-sum-running-total-in-mysql
How to Calculate Cumulative Sum/Running Total in MySQL?
To perform calculations and operations in MySQL, a variety of functions and commands are available. These enable us to manipulate data, perform mathematical computations, and aggregate values. Some commonly used functions in MySQL include SUM, COUNT, AVG, MAX, and MIN. These functions are integral to calculating cumulative sums and running totals.
🌐
Bipp
bipp.io › sql-tutorial › mysql › calculate-cumulative-total
How to Calculate Cumulative Sum-Running Total | Analysis | MySQL | bipp Analytics
Let’s say we want to see a report with cumulative values, for example the cumulative daily revenue at different timestamps. We want the cumulative revenue at each timestamp in the table: select sales_ts, sum(amount) over (partition by sales_ts order by sales_ts) from sales;
🌐
OneUptime
oneuptime.com › home › blog › how to use running totals with sum() over() in mysql
How to Use Running Totals with SUM() OVER() in MySQL
March 31, 2026 - Compute the cumulative total sales across all categories ordered by date. SELECT sale_date, product_category, amount, SUM(amount) OVER (ORDER BY sale_date, id) AS running_total FROM daily_sales ORDER BY sale_date, id;
🌐
Reddit
reddit.com › r/sql › cumulative sum or running sum
r/SQL on Reddit: Cumulative sum or running sum
March 10, 2023 -

Hello!

I am trying to write a SQL query using a combination of CTE and windows function to calculate a cumulative sum of the count of product.

My apologize as I'm using my mobile but here is an example of the dataset

Productcode RATE1 RATE1 RATE3 RATE1 RATE3 RATE2

The original table has a lot of columns but I'm only interested into 1. It also has customer id but a customer can only have 1 product. There is also date row but I'm not interested in the date

I wrote the below with the idea of taking a column out of many from the original dataset, group the product code and get individual count of each rate and finally add a column running a cumulative sum

WITH testtable AS (Select Productcode ,Count(*) as Freq From table group by 1) Select Productcode ,Sum(Freq) over (partition by productcode) as cumul From testtable

The output is essentially a duplicate of the column Freq as opposed to the cumulative Freq as I hoped.

I also appreciate that there is certainly an easier way of getting this done but I still would like to know why it is not working?

Thanks for your inputs!

Edit: moved 'AS' to the correct position Edit 2: sample dataset and further clarifications Edit 3: solved SUM(COLUMN) OVER (ORDER BY productid)

🌐
StrataScratch
stratascratch.com › blog › computing-cumulative-sum-in-sql-made-easy
Computing Cumulative Sum in SQL Made Easy - StrataScratch
May 8, 2025 - In SQL, this means accessing all the previous rows, summing them, and adding the sum to the current row’s value. Imagine you’re working with the table showing the daily sales. The cumulative sum for January 1 is 4,578.00, i.e., the same as the sales value for that date.