Seven-Day Rolling Average
Compute each sale's 7-day rolling average of amount, per account.
Start practiceProblem statement
Prompt
Given the sales table below, write a query that returns each sale with a rolling_avg column: the average of that account's amount over the current sale and the six preceding sales (a 7-row window), ordered by sale_date.
- The window must reset per account.
- Round
rolling_avgto 2 decimal places withROUND(..., 2). - Output columns:
id,account_id,sale_date,amount,rolling_avg. - Order the result by
account_id, thensale_date, thenid. sales.amountmay beNULL;AVGignoresNULLvalues (the window still counts 7 rows, but NULLs don't contribute).
Example
| id | account_id | sale_date | amount |
|---|---|---|---|
| 1 | 1 | 2024-01-01 | 10 |
| 2 | 1 | 2024-01-02 | 20 |
| 3 | 1 | 2024-01-03 | 30 |
Expected result (window has only 3 rows so far):
| id | account_id | sale_date | amount | rolling_avg |
|---|---|---|---|---|
| 1 | 1 | 2024-01-01 | 10 | 10 |
| 2 | 1 | 2024-01-02 | 20 | 15 |
| 3 | 1 | 2024-01-03 | 30 | 20 |
Constraints
sales.idis the primary key.sales.amountis nullable.
Tips
AVG(amount) OVER (PARTITION BY account_id ORDER BY sale_date, id ROWS BETWEEN 6 PRECEDING AND CURRENT ROW).- The frame is row-based: it averages the last 7 _rows_, not 7 calendar days.
Schema
CREATE TABLE sales (
id INTEGER PRIMARY KEY,
account_id INTEGER NOT NULL,
sale_date DATE NOT NULL,
amount INTEGER -- NULL allowed
);
Sample data
INSERT INTO sales (id, account_id, sale_date, amount) VALUES
(1, 1, '2024-01-01', 10),
(2, 1, '2024-01-02', 20),
(3, 1, '2024-01-03', 30),
(4, 1, '2024-01-04', 40),
(5, 2, '2024-01-01', 5),
(6, 2, '2024-01-02', 15),
(7, 2, '2024-01-03', 25);
Additional hidden fixtures are applied during validation to test edge cases.
Solution
One correct approach — try solving it yourself in the practice editor first, then compare. There is usually more than one valid solution.
-- Reference: 7-row rolling average per account.
SELECT id, account_id, sale_date, amount,
ROUND(AVG(amount) OVER (
PARTITION BY account_id
ORDER BY sale_date, id
ROWS BETWEEN 6 PRECEDING AND CURRENT ROW
), 2) AS rolling_avg
FROM sales
ORDER BY account_id, sale_date, id;
Key concepts
- AVG OVER
- ROWS BETWEEN
- PARTITION BY
Related questions
- mediumFirst and Last Order Per CustomerShow the date of each customer's first and last order.
- mediumGame Play Analysis IVFind the fraction of players who logged in the day after their first login.
- mediumRunning TotalCompute a running total of sales over time, partitioned per account.
- mediumConsecutive Login DaysFind users who logged in on three or more consecutive calendar days.
- mediumImmediate Food DeliveryReport the percentage of customers' first orders that were delivered immediately.