BBampaa

Lessons › SQL › Deep Dive: Advanced Window Functions

SQL lesson

Moving averages with AVG() OVER

A moving average (calculated by averaging a sliding window of rows around each point) smooths out short-term noise so the underlying trend becomes visible.

Try this lesson free →
About 5–10 minutes · no sign-up needed

Example

Smoothing Retail Sales Trends with Moving Averages

SELECT sale_date, revenue, AVG(revenue) OVER (ORDER BY sale_date ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) AS moving_avg_3day_revenue FROM store_sales WHERE channel = 'Online' ORDER BY sale_date

Result:

sale_daterevenuemoving_avg_3day_revenue
2024-03-0112400.012400.0
2024-03-029800.011100.0
2024-03-0315200.012466.67
2024-03-0411600.012200.0
2024-03-0513900.013566.67

Step by step

  1. Run the query without AVG so you can see what the unfiltered values look like.
    SELECT sale_date, revenue, revenue OVER (ORDER BY sale_date ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) AS moving_avg_3day_revenue FROM store_sales WHERE channel = 'Online' ORDER BY sale_date;
  2. AVG returns the mean of the values in a column.
    SELECT sale_date, revenue, AVG(revenue) OVER (ORDER BY sale_date ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) AS moving_avg_3day_revenue FROM store_sales WHERE channel = 'Online' ORDER BY sale_date;
  3. AS gives the AVG result a friendly column name so the output reads cleanly.
    SELECT sale_date, revenue, AVG(revenue) AS avg_result OVER (ORDER BY sale_date ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) AS moving_avg_3day_revenue FROM store_sales WHERE channel = 'Online' ORDER BY sale_date;

Practice

Try each one in your head first, then open the answer.

1. Using orders, write a query for a 7-row moving average of revenue ordered by order_date.
SELECT order_date, AVG(revenue) OVER (ORDER BY order_date ROWS BETWEEN 6 PRECEDING AND CURRENT ROW) FROM orders
2. Using store_sales, write a query for a 3-row moving average of revenue ordered by sale_date.
SELECT sale_date, AVG(revenue) OVER (ORDER BY sale_date ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) FROM store_sales
3. Using products, write a query for a 7-row moving average of price ordered by category.
SELECT category, AVG(price) OVER (ORDER BY category ROWS BETWEEN 6 PRECEDING AND CURRENT ROW) FROM products
4. Using employees, write a query for a 3-row moving average of salary ordered by hire_date.
SELECT hire_date, AVG(salary) OVER (ORDER BY hire_date ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) FROM employees
5. Using reviews, write a query for a 3-row moving average of rating ordered by review_date.
SELECT review_date, AVG(rating) OVER (ORDER BY review_date ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) FROM reviews

Learn it by doing. This lesson is a short hands-on level on Bampaa: see it work, then build and write it yourself, with instant feedback.

Try this lesson free →
About 5–10 minutes · no sign-up needed