SQL на собесе аналитика — почему именно эта секция самая важная
Если в 2026 году вы готовитесь к интервью на позицию аналитика, бизнес-аналитика, дата-аналитика или продуктового аналитика — SQL будет на 90% собесов. И эта секция чаще всего топит сильных кандидатов: математика лёгкая, кейс пройден, а простой запрос с окном не сошёлся, и всё.
В этом гиде разберём 30 типов задач, которые реально дают на собесах:
- базовые SELECT-агрегации;
- JOIN-ы во всех вариациях;
- оконные функции;
- gaps-and-islands;
- когортную ретенцию;
- sessionization;
- pivot и unpivot;
- рекурсивные CTE.
К каждому типу — пример задачи из нашего каталога, чтобы можно было пойти и сразу прорешать.
Базовые типы задач (1–5): фундамент
1. Агрегация и GROUP BY с фильтром
Самая простая задача, на которой умудряются ошибаться: «посчитать средний чек по категориям, где более 10 заказов». Подвох — фильтр должен быть в HAVING, а не в WHERE.
Тренировка: Habr · WHERE vs HAVING.
2. Вторая по величине зарплата
Классика всех собесов. Спросят почти везде, потому что задача проверяет, знаете ли вы оконные функции (DENSE_RANK) или умеете обходиться без них.
Тренировка: Habr · Вторая по зарплате и SQL · Вторая зарплата.
3. Удаление дубликатов
В чём разница между DISTINCT, GROUP BY, и оконной функцией ROW_NUMBER() OVER (PARTITION BY ...)? Тренировка: Habr · Удаление дублирующих email.
4. Процент от общего
«Посчитать долю каждой категории в общей выручке». Тренировка: Habr · Процент от общего.
5. Top-N в группе
«Топ-3 продукта в каждой категории». Решается через ROW_NUMBER или DENSE_RANK в PARTITION BY. Тренировка: Habr · Top-3 магазина по городу.
JOIN-ы (6–10): где сыпется большинство
6. INNER vs LEFT JOIN
Понимание: после LEFT JOIN с фильтром в WHERE поведение меняется. Если фильтр должен срабатывать «не нашли — пропустили строку», он в ON, а не в WHERE.
7. Self-join
«Найти сотрудников, которые получают больше своего менеджера». Self-join по таблице на саму себя — мастхэв. Тренировка: Habr · Self-join менеджеров.
8. Anti-join (NOT IN / NOT EXISTS)
«Клиенты без заказов». Должны помнить про ловушку: NOT IN с NULL вернёт пустой результат. Тренировка: Habr · Пользователи без заказов.
9. Cross join и его контролируемое использование
«Сгенерировать сетку дат» — типичная задача, где cross join осознанно нужен. Тренировка: Habr · Заполнение разрывов по датам.
10. FULL OUTER JOIN
Реже, но бывает. Спросят «как объединить две таблицы, чтобы не потерять записи ни в одной». Должны помнить про COALESCE для null-ов.
Оконные функции (11–18): сердцевина middle-задач
11. ROW_NUMBER, RANK, DENSE_RANK
Базовая трилогия. Должны помнить разницу: ROW_NUMBER всегда уникален, RANK оставляет «дырки», DENSE_RANK не оставляет.
12. LAG и LEAD
«Разница между текущим и предыдущим заказом пользователя». Тренировка: Awesome SQL · Скользящее окно % изменений.
13. Cumulative sum (SUM OVER)
Кумулятивная сумма по пользователю или по дате. Тренировка: SQL · Running total по пользователю, Awesome SQL · Running total, Habr · Running monthly sales.
14. Скользящее среднее (Rolling)
7-дневный moving average — must-have для аналитика. Тренировка: LeetCode · Restaurant growth 7-day MA.
15. NTH-row внутри окна
«Третья по дате покупка пользователя». Тренировка: Awesome SQL · Nth row.
16. Медиана с окном
В Postgres есть PERCENTILE_CONT. На MySQL — танец с подзапросами. Тренировка: Awesome SQL · Median, Habr · Median by group.
17. First/Last value в окне
FIRST_VALUE и LAST_VALUE с правильным фреймом. Подвох — без ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING LAST_VALUE ведёт себя не так, как ждёшь.
18. Doable: первая покупка пользователя
«Первая транзакция каждого клиента». Тренировка: Habr · Первая покупка пользователя.
Продвинутые задачи (19–25)
19. Gaps-and-islands: последовательные дни
«Найти максимальную серию подряд активных дней пользователя». Хитрый трюк: вычесть ROW_NUMBER из даты — получится постоянная для группы подряд идущих дней.
Тренировка: SQL · Consecutive streak, Awesome SQL · Consecutive logins, Habr · Consecutive days active.
20. Заполнение пропусков по датам
«Доход по дням, включая дни с нулевым доходом». Cross join + LEFT JOIN. Тренировка: Awesome SQL · Fill gaps.
21. Когортная ретенция
Самая частая «сложная» задача собеса. «Какая доля пользователей, зарегистрированных в январе, оставалась активной через 1, 2, 3 месяца?» Тренировка: SQL · Когортная ретенция помесячно, Habr · Cohort retention.
22. RFM-сегментация
«Распределить клиентов по 3 квантилям Recency, Frequency, Monetary». Тренировка: SQL · RFM-сегментация.
23. Воронка по событиям
«Конверсия search → product → cart → checkout → order». Тренировка: SQL · Воронка заказов по дням, Habr · Воронка конверсии.
24. Sessionization
«Сгруппировать события в сессии — если между событиями прошло > 30 минут, начинается новая сессия». Решается через LAG + накопительная сумма флага.
25. Pivot и unpivot
«Месячные продажи по категориям — каждый месяц колонкой». Тренировка: Habr · Pivot monthly, Awesome SQL · Pivot monthly.
Сложные паттерны (26–30): сеньорный уровень
26. Рекурсивный CTE
«Иерархия сотрудников — кто чей менеджер сверху до самого CEO». Рекурсивный CTE даёт обход дерева. Каждый второй senior-собес содержит такую задачу.
27. Stadium traffic (3+ дня подряд)
Классическая LeetCode-задача. «Найти 3+ дня подряд, где число посетителей > 100». Решается через окно и self-join.
Тренировка: LeetCode · Human traffic stadium.
28. Slowly Changing Dimensions (SCD type 2)
«Цена товара менялась — найти актуальную на момент заказа». Тренировка: SQL · Актуальные цены.
29. Воронка с правильной обработкой повторных событий
Простая воронка проваливается, если пользователь сделал кнопку «обновить» 3 раза. Нужно правильно дедуплицировать, не теряя последовательность.
30. EXISTS vs IN vs JOIN
Производительность одинаковых задач, реализованных по-разному. На сеньорном собесе про это могут спросить — особенно если у компании Postgres или ClickHouse.
Чек-лист подготовки к SQL-собесу
За 4 недели
- Неделя 1: базовые SELECT, JOIN, GROUP BY. Прорешать 20 задач.
- Неделя 2: оконные функции. Прорешать 25 задач.
- Неделя 3: gaps-and-islands, cohort, funnel. 20 задач.
- Неделя 4: pivot, рекурсия, sessionization. 10 задач + mock на 60 минут.
За 1 неделю (срочно)
- День 1–2: оконные функции (ROW_NUMBER, LAG/LEAD, SUM OVER).
- День 3: cohort retention и funnel.
- День 4: gaps-and-islands.
- День 5: pivot.
- День 6: mock-интервью.
- День 7: разбор ошибок и повтор.
За 1 день (катастрофа)
- Перечитать синтаксис оконных функций.
- Прорешать 5 ключевых задач (вторая зарплата, ретенция, воронка, running total, gaps-and-islands).
- Не учить новое — повторить старое.
Топ-10 «инсайтов» SQL-собесов
- WHERE применяется до GROUP BY, HAVING — после. Это любимый теоретический вопрос.
- NOT IN с NULL возвращает пустой результат. Используйте NOT EXISTS.
- LEFT JOIN + WHERE превращается в INNER JOIN. Если хотите сохранить null — фильтр в ON.
- COUNT(*) считает строки, COUNT(колонка) пропускает null. Подвох на сравнении.
SUM(x) OVER (ORDER BY date)по умолчанию накопительная. Полезно знать.- DISTINCT — не функция, это модификатор SELECT.
COUNT(DISTINCT x)работает, аDISTINCT xбез SELECT — нет. ROW_NUMBERгарантированно уникален,RANKоставляет дырки. Помнить разницу.- CTE — это не подзапрос, у него своя оптимизация. На Postgres до 12 — материализованный, после — opt-in.
PARTITION BYбезORDER BYдаёт окно без порядка. Cumulative sum работать не будет.HAVINGбезGROUP BYтоже работает. Применяется к одной «глобальной» группе.
Какие книги/материалы помогают
- «SQL за 10 минут» Бен Форта — базовый учебник.
- «SQL Pocket Guide» O'Reilly — справочник.
- «SQL Antipatterns» Bill Karwin — что НЕ надо делать.
- «Карьера аналитика» Karpov.Courses — практика на реальных задачах.
- LeetCode SQL 50 — для базовой механики.
- StrataScratch — продуктовые SQL-задачи.
Типичные ошибки на SQL-собесе
- Пишут без таймера. На реальном собесе на задачу обычно 10–15 минут.
- Не уточняют схему таблиц. «Какие колонки в orders?» — нормальный вопрос.
- Пишут «оптимально», ломая корректность. Сначала рабочий запрос, потом оптимизация.
- Заучивают шаблоны. Шаблон работает, пока задача типовая. Учитесь рассуждать с нуля.
- Не проверяют запрос. «А что если table A пустая?» — спросите себя сами.
Связанные задачи каталога
Для тренировки соберите такой пул из 25 задач:
- Базовые: Вторая зарплата, Дубли email, Процент от общего, Top-3 по городу, WHERE vs HAVING.
- JOIN: Self-join менеджеров, Без заказов, Заполнение дат.
- Оконные: Running по пользователю, Awesome Running total, Running monthly sales, Restaurant growth MA, Window pct, Nth row, Median by group, Median awesome, First purchase.
- Продвинутые: Streak, Consecutive logins, Consecutive days active, Fill gaps, Cohort ретенция, Cohort retention habr, RFM, Воронка заказов, Воронка конверсии.
- Сложные: Pivot monthly, Pivot awesome, Human traffic stadium, Актуальные цены.
Итого
SQL — это самая «механическая» секция собеса, но именно из-за этого проще всего готовиться. План: 60 задач за 4 недели, mock-интервью каждый weekend, ежедневная практика по 30 минут. К концу подготовки у вас в голове должна быть карта: «вижу задачу — знаю, оконку или CTE; вижу даты — думаю про gaps-and-islands». Когда эта карта появилась — SQL-секцию вы пройдёте.