SQL Playground
TutorialsPlayground
SQL FormatterSQL MinifierSyntax ValidatorJSON to SQLCSV to SQLSQL to JSONER Diagram Generator
Daily ChallengeInterviewsCheat SheetBlog

© 2026 SQL Playground. Built for developers.

PrivacyTermsAboutRSS Feed
SQL Playground
TutorialsPlayground
SQL FormatterSQL MinifierSyntax ValidatorJSON to SQLCSV to SQLSQL to JSONER Diagram Generator
Daily ChallengeInterviewsCheat SheetBlog
Back to Blog
2026-01-16
3 min read

Calculating Running Totals & Moving Averages in SQL

sqlitewindow-functionsanalyticsreportingintermediate

Data analysis is rarely about looking at a single row in isolation. Most business questions involve context:

  • "How does today's revenue compare to yesterday?"
  • "What is our cumulative growth this month?"
  • "What is the moving average trend?"

Before SQLite 3.25 (2018), this required painful self-joins. Now, we have Window Functions.

Running total chart with cumulative line
Running total chart with cumulative line

The Window: OVER()

The OVER clause defines a "window" of rows surrounding the current row.

Cumulative Sum (Running Total)

To calculate a running total, we sum up everything from the start until the current row.

SELECT 
  date, 
  amount,
  SUM(amount) OVER (ORDER BY date) as running_total
FROM sales;

Interactive Example: Revenue Growth

Let's track the revenue of two different stores over time. We want to see:

  1. Daily Revenue: What they made that day.
  2. Cumulative Revenue: Total made since the beginning.
Interactive SQL
Loading...

Understanding PARTITION BY

Notice PARTITION BY store_name above?

This tells SQL to reset the running total whenever it encounters a new store. Without it, Store B would start with Store A's total added to it!

Moving Averages

Business data is noisy. A "7-Day Moving Average" smooths out the spikes to show the true trend.

We use the ROWS BETWEEN frame clause:

AVG(amount) OVER (
  ORDER BY date
  ROWS BETWEEN 2 PRECEDING AND CURRENT ROW -- 3-day average (2 days before + today)
)
Interactive SQL
Loading...

Conclusion

Window functions like SUM() OVER and AVG() OVER are superpowers for reporting.

  • ORDER BY inside OVER defines the sequence.
  • PARTITION BY defines where to restart the calculation.
  • ROWS BETWEEN defines the window size for moving metrics.
Share this article:

Related Articles

window-functionsanalytics

Mastering SQL LEAD and LAG Functions for Row Comparisons

Need to compare a row with its previous or next row? Learn how SQL's LEAD and LAG window functions let you access neighboring rows without complex self-joins.

Read more
analyticswindow-functions

Time Series Analysis with SQL: Trends, Growth, and Moving Averages

Turn raw timestamps into business insights. Learn how to calculate Month-over-Month growth and smooth out noisy data with 7-day moving averages.

Read more
window-functionsanalytics

SQL Window Frames: ROWS vs RANGE

Learn how ROWS and RANGE window frames change results, avoid hidden pitfalls, and build correct moving calculations with clear, runnable examples.

Read more
Previous

Building a Weighted Search Engine with Pure SQL

Next

Mastering SQL LEAD and LAG Functions for Row Comparisons

Comments

© 2026 SQL Playground. Built for developers.

PrivacyTermsAboutRSS Feed