← 30 Days of SQL
Day 13 / 30Window Functions

Running Totals and Moving Averages

Running totals and moving averages are core to financial and operational analytics. These appear in dashboards, MIS reports, and data analyst interviews at banks and e-commerce companies.

1
Medium

Calculate a running total of revenue by month.

SQL Answer
SELECT month, revenue,
       SUM(revenue) OVER (
         ORDER BY month
         ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
       ) AS running_total
FROM monthly_sales;
💡

SUM() OVER with ORDER BY creates a running total. "ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW" is the default frame — it sums everything from the first row to the current row.

2
Hard

Calculate a 3-month moving average of sales.

SQL Answer
SELECT month, revenue,
       AVG(revenue) OVER (
         ORDER BY month
         ROWS BETWEEN 2 PRECEDING AND CURRENT ROW
       ) AS moving_avg_3m
FROM monthly_sales;
💡

"2 PRECEDING AND CURRENT ROW" means: current row + 2 rows before = 3-row window. Moving averages smooth out spikes and reveal trends — commonly used in sales and marketing analytics.

3
Medium

Calculate cumulative count of orders per customer.

SQL Answer
SELECT customer_id, order_date, order_id,
       COUNT(*) OVER (
         PARTITION BY customer_id
         ORDER BY order_date
         ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
       ) AS order_number
FROM orders;
💡

This gives each order a sequential number per customer — showing whether it's the 1st, 2nd, 3rd order. Useful for cohort analysis and repeat purchase tracking.

4
Hard

What is the difference between ROWS and RANGE in window frames?

SQL Answer
-- ROWS: physical rows (faster, more predictable)
SUM(salary) OVER (
  ORDER BY salary
  ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING
)

-- RANGE: logical range of values (groups tied values)
SUM(salary) OVER (
  ORDER BY salary
  RANGE BETWEEN 1 PRECEDING AND 1 FOLLOWING
)
💡

ROWS counts physical rows. RANGE groups rows with identical ORDER BY values. For most analytics use cases, ROWS is the right choice — predictable and faster.

5
Hard

Show the running total of sales that resets each year.

SQL Answer
SELECT year, month, revenue,
       SUM(revenue) OVER (
         PARTITION BY year
         ORDER BY month
         ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
       ) AS ytd_revenue
FROM monthly_sales;
💡

PARTITION BY year resets the running total for each year. This is the Year-to-Date (YTD) pattern — standard in financial reporting.

EVIKA ACADEMY · SQL FOR DATA ANALYTICS

Want to master SQL with live practice?

Join our SQL for Data Analytics course — live classes in Noida and online across India.

Book Free Demo Class →
← PREVIOUSDay 12: Window Functions — LAG and LEADNEXT →Day 14: CASE WHEN
Best Data Analytics Course in Noida Delhi NCR | EVIKA ACADEMY