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 на группу.