Moving Averages

SQL · Extra Concepts

Theory

A moving (rolling) average replaces each value with the average of itself and a fixed number of neighbouring rows, which smooths out day-to-day noise and reveals the trend. A 3-day moving average on day 5 is the average of days 3, 4 and 5; on day 6 the window slides forward to days 4, 5 and 6.

In SQL you write it with a window function and an explicit frame: AVG(amount) OVER (ORDER BY sale_date ROWS BETWEEN 2 PRECEDING AND CURRENT ROW). The frame clause says exactly which rows go into each average. At the start of the data there are fewer rows available, so day 1 averages only itself and day 2 averages two days; filter those rows out or show them with a note if a full window matters. ROWS counts physical rows, so if a day is missing from the table the window silently spans more calendar days. Fill gaps with a calendar table first, or use a RANGE frame with an interval in databases that support it, such as PostgreSQL.

Why we use it

Raw daily numbers jump around because of weekends, promotions and random noise, hiding the real direction. A moving average smooths the series so trends and turning points are easy to see.

When to use it

Use it on time series such as daily sales, signups or sensor readings. Choose a window that matches the cycle (7 days for weekly patterns). Use a running total for to-date figures, and a plain GROUP BY average for one value per period.

How it works

  1. Order rows by date
  2. Define the frame: ROWS BETWEEN 2 PRECEDING AND CURRENT ROW
  3. For each row, collect itself and up to 2 earlier rows
  4. Fewer rows than the window? Yes: Average what exists. No: Average the full window.
  5. Slide forward one row and repeat
  6. Smoothed series alongside the original values

Syntax

AVG(column) OVER (ORDER BY col ROWS BETWEEN n PRECEDING AND CURRENT ROW)

Example

SELECT name, salary,
  AVG(salary) OVER (ORDER BY id ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) AS moving_avg_3
FROM employees;

Key points

SQL topics

Introduction to SQL

Querying Data

Sorting Rows

Limiting Rows

Filtering Rows

Joining Multiple Tables

Grouping Rows

SET Operators

Working with Tables

Modifying Data

Views & Triggers

Conditional Expressions

SQL Subqueries

Aggregate Functions

Window Functions

String Functions

Date Functions

Math Functions

Extra Concepts

T
Tech Town
Log InSign Up Free
Home SQL Python DSA Power BI Snowflake Databricks Spark Gen AI Practice Problems Contest Blog

Master SQL from Zero to Pro

All SQL topics in one place. Click any topic in the sidebar — content opens right here without leaving the page.

{{ sectionCount }}
Sections
{{ topicCount }}
Topics
Free
Forever
Hands-on practice Practice SQL Online Solve 150 SQL interview problems in a live editor with instant checking. Start practising →
Section {{ sec.num }}

{{ sec.label }}

SQL  /  {{ current.sectionLabel }}  /  {{ current.name }}

{{ current.name }}

Theory

{{ current.def }}

Why we use it

{{ rich.why }}

When to use it

{{ rich.when }}

Diagram

{{ rich.dg.caption }}

{{ tb.title }}
{{ c.v }}
{{ rich.dg.op }}
➜
{{ rich.dg.output.title }}
{{ c.v }}
{{ nd.label }}
{{ nd.sub }}
{{ nd.label }}
{{ nd.sub }}
{{ rich.dg.left.title }}
{{ it }}
{{ rich.dg.right.title }}
{{ it }}
Flowchart — how it works
{{ nd.text }}
{{ nd.text }}
◇ {{ nd.text }}
Yes → {{ nd.yes }}
No → {{ nd.no }}
Syntax
{{ current.syntax }}
Example
{{ current.example }}
▶ Try It Live — runs against a real sample database
{{ liveError }}
{{ col }}
{{ cell }}
Key Points — click to check off as you learn
  • {{ pt.mark }} {{ pt.text }}

Share this topic