Running Total SQL: Cumulative Sum Examples

by | SQL

Unlocking the power of data often requires more than just raw numbers; it demands the ability to track and analyze trends over time.

This is where running totals come into play, serving as a pivotal tool in SQL, especially in financial computations and progressive trend analysis.

In SQL, a running total is commonly used in reporting and data analysis to provide cumulative analytics. For instance, a running total of sales would start with the amount of the first sale, then add the amount of the second sale to that, then the amount of the third sale, and so on.

This can be particularly useful when you want to track the accumulated sum, or any other aggregate operation, over a certain grouping.

In this article, we’ll go over the intricacies of running total calculations in SQL, offering practical examples and guidance to deepen your understanding.

By exploring various methods and weighing their merits, you’ll gain a valuable mastery of this powerful tool and apply it to your own data analysis.

Let’s dive in!

What Are Running Totals in SQL?

Running total sql

In SQL, running totals are the cumulative sum of the previous numbers in a column, usually ordered by a unique identifier, like maybe a primary key.

Rolling total, cumulative sum, and running sum are alternate terminologies used to describe running total, but in practice, they all refer to the same calculation technique. This method allows analysts to observe trends and patterns over time, providing valuable insights for decision-making.

Here’s an example to illustrate this concept: if you have a column of daily sales figures, a running total would provide the total sales up to and including the current day.

So, for example, if you sold $100 worth of products on day 1, $200 on day 2, and $150 on day 3, your running total on day 3 would be $450 ($100 + $200 + $150).

Syntax for Running Totals in SQL

The syntax varies depending on the version and type of SQL you’re using. However, one of the most common ways to calculate running total is by using window functions, which are available in many modern SQL versions such as MySQL 8.0+, PostgreSQL, and SQL Server 2012+.

Here’s how the logic and syntax of running total in a SQL query would look like:

SELECT 
   order_id,
   order_date,
   sale_amount,
   SUM(sale_amount) OVER (ORDER BY order_date) AS running_total
FROM 
   Sales;

In this query, Sales is the name of the table, and order_id, order_date, and sale_amount are columns in that table. The SUM(sale_amount) OVER (ORDER BY order_date) part of the SELECT statement calculates the running total of sale_amount.

The ORDER BY clause inside the OVER clause specifies the order in which the rows should be summed to calculate the running total.

Running totals with specific range

The output shows you the running total value of each day organized by order_id:

SQL running total output for sales with order_id as first column

This is a simplified example. The actual implementation can vary depending on your requirements. Some SQL versions also support the PARTITION BY clause inside the OVER clause, which allows you to calculate separate running totals for different groups of rows.

There are a lot of functions and methods you can use to calculate the running total in SQL, which is why our next section focuses on introducing you to different ways that you can use it.

5 Ways to Use for Running Totals in SQL

Running totals are a common requirement in SQL, often used in financial analysis, inventory management, and data reporting.

There are several ways to calculate running totals in SQL, each with its own advantages and disadvantages. Here, we’ll discuss some methods you can use to ease your workflow:

1. Use Window Functions (Partition Data Method)

In SQL, window functions are a feature that allows you to perform calculations across a group of rows that are related to the current row. They are particularly useful for solving problems that involve running totals or cumulative sums.

A window aggregate function enables you to perform aggregate functions over a set of rows that are related to the current row.

The PARTITION BY clause is a function used to divide the output of a query into partitions or groups. These partitions are then used in conjunction with an OVER clause for calculations like averages or sum on each individual partition. It’s often used when working with multiple data groups for aggregated values within each group.

The typical syntax for a window function or the partition method is as follows:

<window function> (<expression>) OVER (
    [PARTITION BY <expression list>]
    [ORDER BY <expression list>]
    [ROWS <frame specification>]
)

Let’s break it down:

  1. <window function>: This is the name of the SQL window function you want to use. Common window functions include SUM, AVG, COUNT, ROW_NUMBER, RANK, and DENSE_RANK.
  2. <expression>: This is the column or expression on which you want to perform the calculation.
  3. OVER clause: The OVER clause is used to specify that the function is a window function.
  4. PARTITION BY <expression list> (optional): This clause divides the result set into partitions (groups of rows) based on one or more expressions. The window function is applied separately to each partition.
  5. ORDER BY <expression list> (optional): This clause determines the order of the rows within each partition.
  6. ROWS <frame specification> (optional): This clause specifies the range of rows around the current row within which the window function will be applied.

Here’s an example:

SELECT order_date, sale_amount, 
SUM(sale_amount) OVER (ORDER BY order_date) as running_total
FROM Sales;

This query uses the SUM function and the OVER clause to calculate the SQL running total. For each row, it sums up the sale_amount for all rows with the same or earlier order_date.

Generate running total with a window function using unique values

The output shows the running total number organized by order_date in our sample table “Sales”

Running total executed with a window function

The window function method is usually much faster than the self-join or subquery methods, especially for large datasets. However, it’s not supported by all SQL databases as the partition method may use some operators or aggregation functions not in use by all.

2. Using Self-Join to Calculate a Running Total

A self-join is a method used to combine rows with other rows in the same table when there’s a match based on some condition. In the context of calculating running totals, a self-join can be used to sum up values from the current row and all previous rows.

Here is how you would use a self-join to calculate running totals. And if you’re stuck constructing basic commands and tables, let ChatGPT do them for you!

SELECT
    s1.order_date,
    s1.sale_amount,
    SUM(s2.sale_amount) AS running_total
FROM 
    Sales s1
JOIN
    Sales s2 ON s1.order_date >= s2.order_date
GROUP BY
    s1.order_date, s1.sale_amount
ORDER BY
    s1.order_date;

In this query, for each row in table s1, we’re using the SUM function on the sale_amount for all rows in table s2 that have the same or earlier order_date. The result is a running total.

Let’s create a simple table named Expenses that’ll consist of columns expense_date and amount.

Using SELF JOIN to calculate the running total in a sample table without duplicate values

For each row, it sums up the amount from that row and all previous rows (based on the expense_date).

The running total here shows the sales amount

However, it’s important to note that the self-join method can be inefficient for large datasets because it requires multiple passes over the data.

For every row in the table, it needs to scan all rows again to calculate the running total. This can lead to performance issues when dealing with large volumes of data.

3. Calculating a Running Total With a Sub-Query

When it comes to calculating running totals in SQL, subqueries can be particularly useful due to their ability to perform calculations on the fly for each row of data.

Here’s why you might use subqueries to compute running totals:

  1. Simplicity: For those who are new to SQL or not familiar with advanced features like window functions, using subqueries to calculate running totals may be more straightforward.

    The logic of a subquery is often easier to understand than a self-join or window function.
  2. Compatibility: Not all SQL dialects support advanced features like window functions, but most support subqueries.

    If your database system doesn’t support window functions, or if you’re writing a query that needs to work across multiple database systems, subqueries can be a good choice.
  3. Sequential processing: In some cases, you may want to calculate a running total in a specific order.

    Subqueries allow you to control the order of operations more precisely than aggregate functions applied over a whole table.
Using subquery to calculate Student marks from a sample table

One advantage of this method is that it’s very flexible and can be tailored to any specific requirement. It’s also more efficient than the self-join approach for small to medium datasets.

This method is similar to the self-join method but can be more efficient in some cases because it avoids a full table join.

Running totals in SQL with the help of a subquery

The result of this query is a list of dates, marks, and running totals. For each date, the running total is the sum of the marks for that date plus all previous dates.

However, it still requires multiple passes over the data, as the subquery is executed once for each row and its value in the table. And if you need to group it by another variable, you can use a pivot function to convert rows into columns.

4. Using a Recursive CTE

A Recursive Common Table Expression (CTE) is a powerful feature of SQL that provides an elegant method to write complex queries.

It can be particularly useful for calculating running totals, where each row’s total is the sum of its value and the previous row’s total.

A recursive CTE is a way to iterate over a set of rows until a certain condition is met.

Let’s work on it with a practical example and start by calculating the running total of a sample data table Sales. The syntax/query we would be using is this:

WITH RunningTotal AS (
    SELECT 
        SalesDate, 
        Amount, 
        CAST(Amount AS FLOAT) AS RunningTotal
    FROM 
        Sales
    WHERE 
        SalesDate = (SELECT MIN(SalesDate) FROM Sales)

    UNION ALL

    SELECT 
        s.SalesDate, 
        s.Amount, 
        CAST(s.Amount + rt.RunningTotal AS FLOAT)
    FROM 
        Sales s
        INNER JOIN RunningTotal rt ON s.SalesDate = DATEADD(month, 1, rt.SalesDate)
)
SELECT * FROM RunningTotal ORDER BY SalesDate;
Code to calculate the running total of our sample table with the recursive CTE method

In this example, the WITH clause is used to define the RunningTotal CTE. The CTE starts with the smallest date and then recursively adds the amount of the next month to the running total from the previous row.

SQL Server output of the running total query executed with the Recursive CTE method

5. Using Cursors to Calculate the Running Totals in SQL

Cursors are database objects used to retrieve rows from a result set one at a time, instead of the T-SQL commands that operate on all the rows in the result set at one time.

Cursors can be particularly useful in scenarios where you need to perform row-by-row operations.

In the context of calculating running totals, you might use a cursor to iterate through a table of transactions, keeping a running total of a certain field, like an account balance, for the following example below.

Here’s a basic example of how you might use a cursor to calculate running totals in SQL Server:

DECLARE @RunningTotal INT = 0;
DECLARE @CurrentValue INT;

DECLARE RunningTotalCursor CURSOR FOR
SELECT Value
FROM YourTable
ORDER BY SomeField;

OPEN RunningTotalCursor;

FETCH NEXT FROM RunningTotalCursor INTO @CurrentValue;

WHILE @@FETCH_STATUS = 0
BEGIN
    SET @RunningTotal = @RunningTotal + @CurrentValue;
    
    PRINT @RunningTotal;
    
    FETCH NEXT FROM RunningTotalCursor INTO @CurrentValue;
END;

CLOSE RunningTotalCursor;
DEALLOCATE RunningTotalCursor;

In this example, YourTable is the name of the sample table and Value is the field or the second column in the table that you’re calculating the running total of.

The cursor retrieves each row in turn, ordered by SomeField. @RunningTotal keeps track of the running total, and @CurrentValue holds the value from the current row.

Here’s a practical example:

Practical example showing using Cursors to calculate the running total in SQL

The output would be:

Output of our query to calculate the running total with the help of a cursor in SQL Server

Though cursors can be useful in specific scenarios, it’s important to note that they can have performance implications. SQL Server and other relational databases are designed to work with sets of data, and operations that work on entire sets of data at once are usually more efficient.

Final Thoughts

Running totals are a valuable tool in data analysis, providing insights into trends and patterns over time. They play a crucial role in various business scenarios, such as sales analysis, inventory management, customer behavior analysis, and more.

SQL, with its powerful window functions and essential commands, makes calculating running totals relatively straightforward.

However, when dealing with large datasets, performance can be a concern.

Proper indexing, partitioning, choosing appropriate data types, and leveraging the power of window functions can significantly improve the speed and efficiency of your queries.

Remember, every dataset and use case is unique, and approaching each with the same process can only lead to one error or another. It’s important to experiment with different approaches, monitor query performance, and fine-tune your strategy accordingly.

You should also keep in mind that understanding the data you’re working with is as important as knowing the technical aspects of SQL. A well-calculated running total can provide valuable insights, but it’s the interpretation of these results that truly drives informed decision-making that makes a difference.

Of course, if you need more practice on getting a good data analyst style workout, check out this video:

Frequently Asked Questions

What is the running total in SQL?

A running total in SQL is a cumulative sum over a sequence of rows, where the value in each row is the sum of all the values in that row and the ones preceding it based on a certain ordering.

It provides the ongoing sum at each point in the set, which can be useful for tracking sums over time, inventory calculations, scores, or other cumulative metrics.

This can be achieved using SQL features such as subqueries, self-joins, or more efficiently through window functions like SUM() OVER (ORDER BY …) in modern SQL databases.

How do I calculate running sum in SQL?

Calculating a running sum in SQL involves determining the cumulative total of a column’s values over a sequence of rows, where the value for each row includes the current row’s value plus the sum of the values in all the preceding rows based on a specified order.

Essentially, it’s a progressive addition that allows you to track the cumulative sum across a series.

What is running total used for?

A running total is used to accumulate a sum over a sequence of values, which can be helpful in numerous scenarios to track and analyze data trends.

In a business context, for example, running totals can be used to monitor cumulative sales over time, facilitating the tracking of overall sales growth.

author avatar
Sam McKay, CFA
Sam is Enterprise DNA's CEO & Founder. He helps individuals and organizations develop data driven cultures and create enterprise value by delivering business intelligence training and education.

Related Posts