Thinking habit: Watch the ties
Running total in SQL with SUM OVER (and the same-day trap)
The question: For each order, show the running total of revenue so far, in order of date, then order id.
orders
| order_id | order_date | amount |
|---|---|---|
| 1 | 2026-03-01 | 100 |
| 2 | 2026-03-01 | 50 |
| 3 | 2026-03-02 | 200 |
| 4 | 2026-03-03 | 75 |
| 5 | 2026-03-03 | 25 |
This query looks right. Run it, decide if it is, and fix it.
Show the answer and why the first query is wrong
Why the usual answer is wrong
SELECT order_id, order_date, amount, SUM(amount) OVER (ORDER BY order_date) AS running_total FROM orders ORDER BY order_date, order_id;
Orders 1 and 2 are on the same day. With only ORDER BY order_date, the window adds up every row with the same date at once, so order 1 already shows 150.
The answer
SELECT order_id, order_date, amount,
SUM(amount) OVER (
ORDER BY order_date, order_id
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
) AS running_total
FROM orders
ORDER BY order_date, order_id;A window with ORDER BY but no frame uses RANGE: rows that tie on the order are added together. Order by something unique (date, then order id) and say ROWS so each row adds only itself.
Add PARTITION BY customer_id to restart the total for each customer.
With a subquery (no window function)
SELECT o.order_id, o.order_date, o.amount,
(SELECT SUM(x.amount) FROM orders x
WHERE x.order_date < o.order_date
OR (x.order_date = o.order_date AND x.order_id <= o.order_id)) AS running_total
FROM orders o
ORDER BY o.order_date, o.order_id;Practise more like this, on real business data
324 interview-style questions on 35 tables with the duplicates, NULLs and missing weeks interviewers test. Free.