What are window functions (ROW_NUMBER, RANK, DENSE_RANK)?
Quick Answer
Window functions compute a value across a set of rows (“window”) related to the current row, without collapsing them like GROUP BY does. Defined with OVER (PARTITION BY ... ORDER BY ...). ROW_NUMBER gives 1,2,3…; RANK leaves gaps after ties (1,1,3); DENSE_RANK doesn't (1,1,2).
Window functions calculate something across a group of rows related to the current row, but unlike GROUP BY they don't collapse the rows — every row stays and gets an extra computed column. You use OVER (PARTITION BY ... ORDER BY ...). ROW_NUMBER gives a clean 1,2,3 per partition, which is how I get the most recent row per customer or do reliable pagination. RANK and DENSE_RANK differ in how they handle ties — RANK leaves a gap, DENSE_RANK doesn't. And aggregate window functions give running totals. The catch is you can't filter on them in WHERE, so I put the numbering in a CTE and filter outside it.
ROW_NUMBER()— unique sequential number per partition. The standard way to get “the latest row per customer” or paginate deterministically.RANK()/DENSE_RANK()— ranking with tie handling; RANK skips numbers after a tie, DENSE_RANK doesn't.- Aggregates as windows —
SUM(Total) OVER (PARTITION BY CustomerId ORDER BY OrderDate)gives a running total. - Top-N per group: number the rows in a CTE, then filter
WHERE rn <= 3. - They run after
WHERE/GROUP BY/HAVINGbut beforeORDER BY, so you can't filter on a window function inWHERE— wrap it in a CTE or subquery.
WITH Ranked AS (
SELECT o.*,
ROW_NUMBER() OVER (PARTITION BY CustomerId
ORDER BY OrderDate DESC) AS rn
FROM dbo.Orders o
)
SELECT * FROM Ranked WHERE rn = 1;