SQL Boy
TutorialsPlayground

Format & Validate

SQL FormatterSQL MinifierSyntax Validator

Convert

JSON to SQLCSV to SQLSQL to JSONRegex to SQLExcel to SQLSQL Dialect Convertersoon

Visualize

ER Diagram GeneratorSQL Schema Diff

Generate

SQL Mock Data Generator

Analyze

SQL Query ExplainerSQL Query Analyzer

Workflow hubs

FormattingConversionSchemaAnalysis
View all tools
Daily ChallengeInterviewsCheat SheetBlog

© 2026 SQL Boy. Built for developers.

ContactPrivacyTermsAI Usage PolicyEditorial StandardsAboutRSS Feed

New conversation

What can I help with?

Ask about this page, get a hint on a challenge, or explore SQL concepts.

I know what's on this page and can give answers grounded in SQL Boy content.

Current page

Calculating Moving Averages In Sql

/blog/calculating-moving-averages-in-sql

Usage status will load after login
SQL Boy
TutorialsPlayground

Format & Validate

SQL FormatterSQL MinifierSyntax Validator

Convert

JSON to SQLCSV to SQLSQL to JSONRegex to SQLExcel to SQLSQL Dialect Convertersoon

Visualize

ER Diagram GeneratorSQL Schema Diff

Generate

SQL Mock Data Generator

Analyze

SQL Query ExplainerSQL Query Analyzer

Workflow hubs

FormattingConversionSchemaAnalysis
View all tools
Daily ChallengeInterviewsCheat SheetBlog
Back to Blog
Published 2025-12-29
Updated 2026-04-20
6 min read

Calculating Moving Averages and Rolling Windows in SQL

sqltutorialtime-serieswindow-functionsmoving-average

Author

SQL Boy Team

Editorial Team at SQL Boy

This article is maintained as part of SQL Boy's hands-on SQL library.

We aim to keep examples runnable, call out dialect differences, and revise unclear sections over time.

Read editorial standardsAbout SQL BoyRequest a correction

If a result or dialect note looks wrong, email [email protected] with the article URL and the section you want reviewed.

Data is noisy. Daily sales spike on weekends, drop on holidays, and fluctuate randomly. To see the real trend, analysts use Moving Averages (or Rolling Averages).

A jagged time series smoothed by a rolling moving average line
A jagged time series smoothed by a rolling moving average line

A moving average takes the current value and averages it with a set number of previous values.

A Real Business Scenario: Distinguishing Trend from Noise

Teams usually reach for moving averages when raw daily values are too noisy to act on directly.

Common examples:

  • finance wants a smoother revenue trend than one-day spikes
  • operations wants to see baseline traffic without every campaign burst dominating the chart
  • product teams want to separate short-lived anomalies from durable growth

The moving average is valuable because it preserves sequence while reducing volatility. It does not replace the raw metric. It gives you a second lens for interpreting it.

The Window Function Formula

Window frame diagram highlighting ROWS BETWEEN 2 PRECEDING AND CURRENT ROW
Window frame diagram highlighting ROWS BETWEEN 2 PRECEDING AND CURRENT ROW

To calculate a moving average in SQL, you use the standard AVG() aggregate function but apply it over a "window" of rows.

AVG(column) OVER (
  ORDER BY date_column
  ROWS BETWEEN X PRECEDING AND CURRENT ROW
)
  • ORDER BY date_column: Ensures rows are processed in chronological order.
  • ROWS BETWEEN: Defines the "frame size".
    • For a 7-Day Moving Average, you want today + the previous 6 days. So: ROWS BETWEEN 6 PRECEDING AND CURRENT ROW.
    • For a 3-Day Moving Average: ROWS BETWEEN 2 PRECEDING AND CURRENT ROW.

A Common Mistake: Confusing Row Windows with Calendar Windows

This is one of the most common moving-average mistakes:

AVG(value) OVER (
  ORDER BY event_date
  ROWS BETWEEN 6 PRECEDING AND CURRENT ROW
)

That is a 7-row moving average, not necessarily a 7-day moving average. If dates are missing, weekends are excluded, or data is sparse, the frame still counts rows, not calendar days.

If the business question is truly time-based, you may need a filled date spine or a database feature that supports interval-aware range framing.

Real-World Example: Daily Stock Prices

Let's look at a volatile stock price and smooth it out.

1. Daily Volatility

First, observe the raw daily prices.

Interactive SQL
Loading...

2. Calculating the 3-Day Moving Average

Now, let's calculate the 3-day moving average. For Jan 3rd, it will average prices from Jan 1, 2, and 3.

Interactive SQL
Loading...

Result Analysis:

  • On Jan 4, the price dropped to $90.
  • The Moving Average was (102+104+90)/3 = 98.66.
  • Notice how the moving average ($98.66) is less extreme than the drop ($90), showing the smoothing effect.

Handling the "Start" of the Window

You might notice that the first row is just the average of itself, and the second row is the average of 2 days. The window grows until it hits the full size (3 days).

If you want to strictly enforce that you ONLY calculate when you have full 3 days of data, you'd need slightly more complex logic (often involving COUNT() OVER (...) to check the window size), but for most visual trend/charting purposes, the growing window at the start is acceptable.

Centered vs Trailing Windows

The examples above differ from "Centered" moving averages, which look ahead and behind.

  • Trailing (Standard): ROWS BETWEEN 2 PRECEDING AND CURRENT ROW
  • Centered: ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING

Centered averages are good for historical analysis but impossible for real-time forecasting (since you don't know tomorrow's price yet!).

Boundary and Performance Notes

Moving averages are usually straightforward after the underlying grain is correct, but there are still common pitfalls:

  • duplicate timestamps can make ordering ambiguous unless you add a deterministic tie-breaker
  • sparse time series can make a row-based frame tell the wrong business story
  • large partitions require sorting, so indexes or clustering on the ordering column still matter
  • smoothing can hide the very spikes that an operations or fraud team needs to investigate

The right workflow is often:

  1. establish the correct daily or hourly aggregate
  2. confirm the ordering column really defines the series
  3. decide whether the window is row-based or calendar-based
  4. plot both the raw metric and the smoothed metric

When NOT to Use a Moving Average

Avoid defaulting to a moving average when:

  • the audience needs exact daily values for operational action
  • the anomaly itself is more important than the baseline trend
  • the series is too short for the chosen window size to be meaningful

A moving average is a smoothing tool, not a universal "better metric".

Official References

  • PostgreSQL window function documentation for window-function semantics and framing concepts.
  • SQLite window function documentation for SQLite support and syntax.
  • PostgreSQL tutorial on window functions for a readable explanation of ordered analytical calculations.

Practice Challenge

Try modifying the query to calculate a Cumulative Average (running average of all time) by removing the ROWS clause entirely or using ROWS UNBOUNDED PRECEDING.

Tool Workflow

Use tools when rolling-window SQL is readable in pieces but hard to trust end to end

Moving-average queries often mix ordering, frame rules, and time-series assumptions. Use the tools to inspect the final window clause and confirm that the calculation matches the business question.

SQL Query Explainer

Break rolling-window queries into readable clauses so ORDER BY and ROWS BETWEEN logic are easier to verify.

Query Analysis Workflow Hub

Use the broader workflow when time-series SQL needs explanation, validation, and result-shape review together.

Conclusion

Window functions with frame specifications (ROWS BETWEEN) give you precise control over rolling calculations. Whether it's stock prices, website traffic, or server load, Moving Averages help you ignore the noise and focus on the signal.

Related Articles

  • Calculating Running Totals & Moving Averages in SQL for the adjacent cumulative-metric pattern that often appears alongside smoothing.
  • SQL Window Frames: ROWS vs RANGE for the frame semantics that cause many subtle rolling-metric bugs.
  • Time Series Analysis with SQL: A Practical Guide for the broader analytical context where moving averages become useful.
Share this article:

Related Articles

sqltutorial

Year-over-Year Growth Analysis in SQL

Calculate growth rates like a pro. Learn how to use the LAG() window function to compare current values with past data.

Read more
sqlwindow-functions

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
sqltime-series

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
Previous

Data Cleaning with SQL: From Messy to Masterpiece

Next

Customer Segmentation with RFM Analysis in SQL

Comments

© 2026 SQL Boy. Built for developers.

ContactPrivacyTermsAI Usage PolicyEditorial StandardsAboutRSS Feed