Your Running Total Is Wrong on the First Row: Window Functions, RANGE, and the Default Nobody Reads
GROUP BY collapses rows; a window function keeps every row while still computing the group total. Measured: on the same 200,000-row table, GROUP BY returns 200 rows and the window returns 200,000 rows. It is also faster than the old approach — replacing a self-join with a window took the query from 79.2 ms down to 22.7 ms. But there is one default that quietly corrupts numbers and almost nobody reads it: OVER (ORDER BY ...) uses a RANGE frame, so every peer row receives the same running total. If you want a row-by-row cumulative sum, you must spell out ROWS.
Window functions turn long-winded reporting queries into a few readable lines. They also carry exactly one trap subtle enough to pass code review: a running total that looks plausible in the middle and is wrong wherever values tie.
This post goes deeper into Recursive Queries and Window Functions from the 30-day SQL series. Every number here was measured on PostgreSQL 16.11.
