DEV Community

Cover image for SQL Pattern Series #7: The Running Total Pattern
Baldwin Apps
Baldwin Apps

Posted on

SQL Pattern Series #7: The Running Total Pattern

Seeing how values build over time

SQL Pattern Series #7 of 21

A collection of practical SQL patterns that help developers recognize common solutions to recurring database problems.

What You'll Learn

In this article you'll learn:

  • What a running total is
  • How SUM() works as a window function
  • Why ORDER BY matters inside OVER()
  • When to use running totals in reports and dashboards

Most reports show totals.

But sometimes a single total is not enough.

You may also need to see how that total builds over time.

For example:

What were cumulative sales by day?

or:

How did the balance grow after each transaction?

That is where the Running Total Pattern becomes useful.


The Problem

Imagine a daily sales table:

Region OrderDate DailyTotal
West 2024-01-01 100
West 2024-01-02 150
West 2024-01-03 75
East 2024-01-01 200
East 2024-01-02 50

A regular total can tell you the final amount.

But it does not show the path.

A running total shows how the value accumulates row by row.



The Running Total Pattern

The Running Total Pattern uses a window function to calculate a cumulative total.

The common structure looks like this:

SUM(column) OVER (
    PARTITION BY column
    ORDER BY column
)
Enter fullscreen mode Exit fullscreen mode

The SUM() calculates the total.

The OVER() clause defines the window.

PARTITION BY restarts the calculation for each group.

ORDER BY controls the sequence in which values accumulate.


Example

SELECT
    Region,
    OrderDate,
    DailyTotal,
    SUM(DailyTotal) OVER (
        PARTITION BY Region
        ORDER BY OrderDate
    ) AS RunningTotal
FROM DailySales;
Enter fullscreen mode Exit fullscreen mode

This query calculates a running total for each region.

For the West region, the running total builds across West rows.

For the East region, the running total starts over and builds across East rows.


Example Result

Region OrderDate DailyTotal RunningTotal
West 2024-01-01 100 100
West 2024-01-02 150 250
West 2024-01-03 75 325
East 2024-01-01 200 200
East 2024-01-02 50 250

The running total shows the cumulative value after each row.

Instead of only seeing the final total, you can see how the total grows.


Why This Pattern Matters

Running totals are useful because they show progression.

They help answer questions like:

  • How much has accumulated so far?
  • When did the total pass a threshold?
  • How quickly is value building?
  • How does one group compare to another over time?

This makes the pattern useful for:

  • sales reporting
  • finance reports
  • inventory tracking
  • account balances
  • progress dashboards

PARTITION BY Controls the Reset

One important part of the pattern is:

PARTITION BY Region
Enter fullscreen mode Exit fullscreen mode

This tells SQL:

Calculate a separate running total for each region.

Without PARTITION BY, SQL calculates one running total across the entire result set.

That may be correct in some cases.

But if you need one running total per customer, region, account, product, or category, PARTITION BY defines where the total resets.


ORDER BY Controls the Story

The other important part is:

ORDER BY OrderDate
Enter fullscreen mode Exit fullscreen mode

A running total depends on sequence.

If the rows are ordered differently, the running total changes.

That means the ORDER BY inside the window function is not just formatting.

It defines the logic of the calculation.


A Note on Ties

If two rows have the same OrderDate, the database may not have a predictable order between them.

For example:

ORDER BY OrderDate
Enter fullscreen mode Exit fullscreen mode

may not be enough if multiple rows share the same date.

If the result must be deterministic, add a tiebreaker:

SUM(DailyTotal) OVER (
    PARTITION BY Region
    ORDER BY OrderDate,
             SaleID
) AS RunningTotal
Enter fullscreen mode Exit fullscreen mode

Now SQL has a stable order when two rows have the same date.


Running Total vs Moving Sum

The Running Total Pattern is closely related to the Moving Sum Pattern.

But they answer different questions.

A running total asks:

How much has accumulated so far?

A moving sum asks:

What is the total over the most recent window?

Running totals keep building.

Moving sums slide forward.

Both are useful, but they tell different stories.


When I Reach for This Pattern

I typically use the Running Total Pattern when:

  • values accumulate over time
  • I need cumulative totals
  • each row should show progress so far
  • totals need to restart by group

Examples include:

  • cumulative sales by region
  • running account balances
  • inventory movement over time
  • cumulative signups
  • progress toward a goal

Key Takeaway

Regular totals show the final number.

Running totals show how the number builds.

The Running Total Pattern helps answer:

How much has accumulated so far?

That makes it one of the most useful patterns for reports, dashboards, and trend analysis.


SQL Pattern Series

This article is part of the SQL Pattern Series, a collection of practical SQL patterns that help developers recognize common problem-solving approaches found in reporting, analytics, and application development.

Previous articles:

  • SQL Pattern Series #1: The Presence Pattern
  • SQL Pattern Series #2: The Match Pattern
  • SQL Pattern Series #3: The Missing Data Pattern
  • SQL Pattern Series #4: The Moving Sum Pattern
  • SQL Pattern Series #5: The Deduplication Pattern
  • SQL Pattern Series #6: The Routing Pattern

SQL Bubble Pop

If you are learning SQL or helping others learn SQL, I created SQL Bubble Pop, a mobile game that teaches SQL concepts through quick, interactive challenges and pattern recognition exercises.

The goal is simple:

Learn SQL by recognizing patterns instead of memorizing syntax.

Top comments (0)