Running Total
Compute a running total of sales over time, partitioned per account.
Start practiceProblem statement
Prompt
Given the sales table below, write a query that returns each sale with a running_total column showing the cumulative sum of that account's sales up to and including the current sale, ordered by sale_date.
- The running total must reset per account (each account's totals are computed independently).
- Output columns:
id,account_id,sale_date,amount,running_total. - Order the result by
account_id, thensale_date, thenid— sales sharing a date must have a deterministic order (useidas the tiebreaker). sales.amountmay beNULL;SUMignoresNULLvalues.
Example
| id | account_id | sale_date | amount |
|---|---|---|---|
| 1 | 1 | 2024-01-01 | 100 |
| 2 | 1 | 2024-01-05 | 50 |
| 3 | 2 | 2024-01-02 | 30 |
Expected result (first two rows shown):
| id | account_id | sale_date | amount | running_total |
|---|---|---|---|---|
| 1 | 1 | 2024-01-01 | 100 | 100 |
| 2 | 1 | 2024-01-05 | 50 | 150 |
| 3 | 2 | 2024-01-02 | 30 | 30 |
Constraints
sales.idis the primary key.sales.amountis nullable.
Tips
SUM(amount) OVER (PARTITION BY account_id ORDER BY sale_date, id ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW).- Omitting
PARTITION BYgives a global running total — a common interview trap.
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', 100),
(2, 1, '2024-01-05', 50),
(3, 1, '2024-01-10', 25),
(4, 2, '2024-01-02', 30),
(5, 2, '2024-01-03', 20),
(6, 2, '2024-01-09', 40);
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: per-account running total, deterministic order via id tiebreaker.
SELECT id, account_id, sale_date, amount,
SUM(amount) OVER (
PARTITION BY account_id
ORDER BY sale_date, id
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
) AS running_total
FROM sales
ORDER BY account_id, sale_date, id;
Key concepts
- SUM OVER
- ROWS BETWEEN
- PARTITION BY
- Tiebreakers
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.
- mediumSeven-Day Rolling AverageCompute each sale's 7-day rolling average of amount, 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.