Оконные функции SQL на собеседовании аналитика
Почему оконные функции спрашивают всегда
Оконные функции — граница между junior и middle на собеседовании аналитика. Кандидат, который уверенно работает с ROW_NUMBER, RANK, LAG и SUM OVER, сразу показывает, что умеет решать реальные аналитические задачи, а не просто писать SELECT с WHERE.
На типичном техническом интервью оконные функции занимают от одного до трёх вопросов. Формат разный: от теоретического «чем отличается RANK от DENSE_RANK» до задачи на доске «напишите запрос, который найдёт второй заказ каждого пользователя».
Оконные функции — тема номер один для middle-аналитиков. Если вы уверенно объясняете разницу между ROW_NUMBER, RANK и DENSE_RANK, интервьюер понимает, что вы работали с реальными данными.
Что именно спрашивают
ROW_NUMBER vs RANK vs DENSE_RANK — классический вопрос. Интервьюер ждёт, что вы объясните поведение при одинаковых значениях: ROW_NUMBER всегда даёт уникальный номер, RANK пропускает позиции при дубликатах, DENSE_RANK не пропускает. Часто просят привести пример, где выбор между ними меняет результат.
LAG и LEAD — функции смещения. Задачи на вычисление разницы между текущей и предыдущей строкой: рост выручки день ко дню, время между сессиями пользователя, изменение метрики за период. Важно помнить про третий аргумент — значение по умолчанию, когда предыдущей строки нет.
SUM, AVG, COUNT с OVER — агрегаты в оконном контексте. Нарастающий итог регистраций, скользящее среднее DAU за 7 дней, доля каждого заказа от общей суммы пользователя. Эти задачи проверяют, понимаете ли вы разницу между обычным GROUP BY и оконной агрегацией.
ROWS BETWEEN — продвинутый уровень. Интервьюер может спросить, чем ROWS отличается от RANGE, или попросить задать рамку для скользящего среднего. Ключевой нюанс: без явного указания рамки при наличии ORDER BY используется RANGE, что ведёт себя неожиданно при дубликатах.
Типичные задачи с разбором
Задача 1: Первый заказ каждого пользователя. Подход — пронумеровать заказы через ROW_NUMBER с PARTITION BY user_id и ORDER BY order_date, затем отфильтровать строки с номером 1. Частая ошибка — использовать MIN(order_date) с GROUP BY, теряя остальные колонки заказа.
Задача 2: Рост выручки день ко дню. Подход — через LAG получить выручку предыдущего дня, вычислить разницу и процент изменения. Ловушка — забыть обработать NULL для первой строки, где предыдущего значения нет.
Задача 3: Нарастающий итог с начала месяца. Подход — SUM с OVER и PARTITION BY по месяцу, ORDER BY по дате. Интервьюер проверяет, понимаете ли вы, что нарастающий итог сбрасывается в каждом новом окне (партиции).
Задача 4: Топ-3 товара по выручке в каждой категории. Подход — ROW_NUMBER или DENSE_RANK с PARTITION BY category ORDER BY revenue DESC, затем фильтрация. Тонкость — выбор между ROW_NUMBER и DENSE_RANK зависит от того, как обрабатывать товары с одинаковой выручкой.
Типичные ошибки кандидатов
- Путают PARTITION BY и GROUP BY — оконная функция не сворачивает строки, а GROUP BY сворачивает. Это фундаментальная разница.
- Забывают ORDER BY в функциях ранжирования — без сортировки результат не определён и может меняться при каждом запуске.
- Не учитывают рамку по умолчанию — при ORDER BY без явного ROWS BETWEEN рамка включает все строки от начала окна до текущей. При дубликатах в сортировке это даёт неожиданные результаты.
- Используют оконные функции в WHERE — оконные функции нельзя фильтровать напрямую. Нужен подзапрос или CTE.
Как готовиться
Теория оконных функций укладывается в одну страницу. Настоящая подготовка — это практика: решить 20-30 задач разного типа, пока паттерны не станут автоматическими. Начните с ROW_NUMBER и LAG, затем переходите к SUM OVER с рамками. Подробную шпаргалку с синтаксисом и примерами смотрите в статье Оконные функции SQL: шпаргалка.
В Карьернике есть вопросы по оконным функциям с разборами — можно тренироваться по 15 минут в день и за неделю довести тему до автоматизма.
Совет: большинство оконных задач на собеседовании решаются шаблоном OVER(PARTITION BY ... ORDER BY ...). Выучите его до автоматизма — и 80% вопросов перестанут вызывать затруднения.
FAQ
Какие оконные функции спрашивают чаще всего?
ROW_NUMBER, RANK и LAG/LEAD — абсолютные лидеры. За ними идут SUM OVER для нарастающих итогов и AVG OVER для скользящих средних. Обязательно знайте разницу между ROW_NUMBER, RANK и DENSE_RANK — этот вопрос задают почти на каждом собеседовании.
Нужно ли знать ROWS BETWEEN для junior-позиции?
Для junior обычно достаточно ROW_NUMBER, LAG и базового SUM OVER. Рамки (ROWS BETWEEN) — это уровень middle и выше. Но если вы покажете знание рамок на junior-собеседовании, это будет сильным плюсом.
Можно ли обойтись без оконных функций и решить задачу через GROUP BY?
Иногда да, но решение будет громоздким: потребуются подзапросы, self-join или несколько запросов. Оконные функции решают такие задачи в одну строку. Интервьюер оценит именно оконное решение — оно показывает зрелость мышления.