IntermediateAdvanced PostgreSQL

Window function frame modes: ROWS vs RANGE

The query

SQL
-- ROWS: physical rows
SELECT
  order_date::DATE,
  total,
  SUM(total) OVER (
    ORDER BY order_date::DATE
    ROWS BETWEEN 2 PRECEDING AND CURRENT ROW
  ) AS rows_3day_sum,

-- RANGE: logical range (all rows with same ORDER BY value)
  SUM(total) OVER (
    ORDER BY order_date::DATE
    RANGE BETWEEN INTERVAL '2 days' PRECEDING AND CURRENT ROW
  ) AS range_3day_sum,

-- GROUPS: frame by peer groups (PostgreSQL 11+)
  SUM(total) OVER (
    ORDER BY order_date::DATE
    GROUPS BETWEEN 2 PRECEDING AND CURRENT ROW
  ) AS groups_3day_sum
FROM orders
WHERE status = 'completed'
ORDER BY order_date;
Tested against PostgreSQL 16

Note

ROWS = exact row count. RANGE = value-based (ties included). GROUPS = distinct values. Different results for ties!

Tables referenced