CoreTrail

ROWS, RANGE & GROUPS

Separate row positions, value distances, and peer groups.

CorePostgreSQL3 min read
On this page
Mode What the offset measures Typical use
ROWS Row positions Previous three records
RANGE Ordering-value distance; peer rows share boundaries Previous six calendar days plus today
GROUPS Groups of equal ordering values Previous distinct score group

Why ties matter

Suppose transactions are (id, amount) = (1,10), (2,10), (3,20):

WITH t(id, amount) AS (VALUES (1, 10), (2, 10), (3, 20))
SELECT id, amount,
       SUM(amount) OVER (
           ORDER BY amount, id
           ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
       ) AS row_total,
       SUM(amount) OVER (
           ORDER BY amount
           RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
       ) AS peer_total
FROM t
ORDER BY amount, id;
id amount row_total peer_total
1 10 10 20
2 10 20 20
3 20 40 40

The RANGE result includes both equal-amount rows together. PostgreSQL’s default ordered frame has this peer-inclusive behavior. Specify ROWS explicitly for a running total that advances one record at a time.

Seven calendar dates, including the current date

SELECT sale_date, revenue,
       SUM(revenue) OVER (
           ORDER BY sale_date
           RANGE BETWEEN INTERVAL '6 days' PRECEDING AND CURRENT ROW
       ) AS revenue_last_7_dates
FROM daily_sales
ORDER BY sale_date;

Assume sale_date is a DATE. This includes observed dates from sale_date - 6 through sale_date, even if intermediate dates are absent. In contrast, ROWS BETWEEN 6 PRECEDING AND CURRENT ROW can reach farther back when dates are missing.

For a timestamp ordering key, an interval range is a time-distance window; it is not automatically a calendar-date bucket. PostgreSQL requires one ordering expression for offset-based RANGE frames. GROUPS and interval-frame support differ across databases.

References

Type a concept, keyword, or function.