intermediate
Window functions
Вычисляйте ranks, running totals, partitions и row comparisons без collapse result rows.
Оконные функции считают результат на каждой строке по партиции, не схлопывая строки как `GROUP BY`. Нужны для ранжирования, накопительных сумм и сравнения периодов в SQL.
SELECT
employee_id,
department,
salary,
rank() OVER (PARTITION BY department ORDER BY salary DESC) AS dept_rank,
sum(salary) OVER (PARTITION BY department) AS dept_payroll,
salary - lag(salary) OVER (PARTITION BY department ORDER BY hire_date) AS raise_delta
FROM employees;
-- Дедуп: последняя строка на ключ
SELECT * FROM (
SELECT *, row_number() OVER (PARTITION BY user_id ORDER BY updated_at DESC) AS rn
FROM events
) s WHERE rn = 1;
Ключевые части: `PARTITION BY` — группы; `ORDER BY` внутри OVER — порядок кадра; frame (`ROWS BETWEEN`) — скользящее окно. DISTINCT ON — альтернатива «top per group», если индексы совпадают.
На интервью: отличие от GROUP BY; пример rank или running total; когда window dedupe лучше коррелированного подзапроса.
Типовые ошибки: нет ORDER BY в OVER (неопределённый rank); огромные партиции без индексов; окна там, где проще и дешевле обычный aggregate.
Компромисс — выразительная аналитика в одном запросе против стоимости сортировки и менее читаемого SQL для команды.
Чеклист:
- Объясните смысл PARTITION BY и ORDER BY.
- Знайте rank vs dense_rank vs row_number.
- Frames — для накопительных и скользящих сумм.
- Сравните DISTINCT ON или LATERAL для top-N на группу.