ROW_NUMBER()
Syntax, PARTITION BY, pagination, deduplication, and latest row per group.
Read guidePostgreSQL SQL
Use this guide to choose the right function, write predictable queries, and jump to complete examples for each pattern.
Window functions calculate a value across related rows without collapsing the result into one row per group. ORDER BY inside OVER() defines the window order, and PARTITION BY restarts the calculation for every group.
SELECT customer_id,
created_at,
ROW_NUMBER() OVER (
PARTITION BY customer_id
ORDER BY created_at DESC
) AS row_number
FROM orders;
| Function | Use it when | Ties |
|---|---|---|
| ROW_NUMBER() | You need a unique number per row, pagination, or the latest row per group. | Broken arbitrarily unless you add a tiebreaker. |
| RANK() | You want to preserve the position consumed by a tie. | Creates gaps. |
| DENSE_RANK() | You want ranking without gaps. | No gaps. |
| LAG() / LEAD() | You need to compare a row with the previous or next row. | — |
Syntax, PARTITION BY, pagination, deduplication, and latest row per group.
Read guideUnderstand ties and choose the correct ranking function.
Read guideCompare previous and next values in time series.
Read guideUse EXPLAIN ANALYZE to compare estimates and actual rows before changing indexes or parameters. To observe regressions and production patterns, monitor query behavior over time.