Какие оконные функции в SQL вы знаете?
Что проверяют
Умеете ли вы считать по строкам, не схлопывая их, и чем окно отличается от GROUP BY. Почти всегда следом дают задачу: вывести топ-3 заказа в каждой категории или посчитать изменение метрики к прошлому месяцу.
Как отвечать
Оконная функция считает значение по набору строк, связанных с текущей, и возвращает его в каждую строку: количество строк не меняется. Окно задаётся в OVER (PARTITION BY ... ORDER BY ... ROWS BETWEEN ...). Дальше назовите группы:
- ранжирующие:
ROW_NUMBER,RANK,DENSE_RANK,NTILE. На двух равных значениях первые три дают 1, 2, 3, затем 1, 1, 3 и 1, 1, 2; - смещения:
LAGиLEADберут значение из предыдущей или следующей строки,FIRST_VALUE,LAST_VALUE,NTH_VALUEиз заданной позиции рамки; - агрегатные в окне:
SUM,AVG,COUNT,MIN,MAXсOVER. Так считают нарастающий итог, долю строки в сумме группы, скользящее среднее; - распределения:
PERCENT_RANK,CUME_DIST.
Упомяните рамку. Если в окне есть ORDER BY, по умолчанию действует RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW, поэтому SUM становится нарастающим итогом. Без ORDER BY рамка это вся партиция. ROWS считает физические строки, RANGE объединяет строки с одинаковым значением сортировки.
И порядок выполнения: окна считаются после WHERE, GROUP BY и HAVING, поэтому фильтровать по ROW_NUMBER в том же WHERE нельзя. Нужен подзапрос или CTE, а в Snowflake, BigQuery и DuckDB есть QUALIFY.
Где спотыкаются
Берут ROW_NUMBER для «топ-3», не думая о равных значениях: при ничьей одна из строк выпадает случайно. Нужно либо решить, что делать с ничьей, либо взять DENSE_RANK.
Пишут LAST_VALUE(x) OVER (ORDER BY d) и получают текущую строку. Из-за рамки по умолчанию нужно явно указать ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING.
Считают среднее за неделю через ROWS BETWEEN 6 PRECEDING AND CURRENT ROW, когда в данных есть пропущенные дни. Получается среднее по семи записям, а не по семи календарным дням: сначала достройте календарь.