💡 Никогда не работал с SQL? Сначала пройди серию SQL с нуля для аналитика — 10 связанных частей от «что такое БД» до Window Functions.
Собеседование аналитика данных в 2026 — это 2-3 этапа: live SQL-coding, продуктовое мышление, A/B-кейс. SQL — фильтр первого этапа. Если запорол JOIN или окошки — дальше не пойдёт.
Я разобрал реальные вопросы из 30+ собесов в РФ и СНГ за последние 12 месяцев. Yandex, Avito, Ozon, Wildberries, Tinkoff, X5, Сбер, VK — каждая компания специфична, но 80% вопросов пересекаются.
Этот пост — карта что спрашивают и где это тренировать. С пояснениями подводных камней. Все 50 разборов с интерактивными SQL-песочницами доступны в тренажёре.
Блок 1: JOIN — без них никуда (вопросы 1-10)
Шаг 1: Различие INNER / LEFT / RIGHT / FULL OUTER JOIN
Базовый вопрос — джуниоры путают LEFT и INNER, когда NULL появляются в результате.
Подвох: LEFT JOIN ... WHERE right_table.col = 'X' ведёт себя как INNER. Правильно — фильтр в ON.
-- Неправильно (теряет «осиротевших» customers)
SELECT c.id, o.amount
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.id
WHERE o.status = 'paid';
-- Правильно
SELECT c.id, o.amount
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.id AND o.status = 'paid';
Шаг 2: Anti-join — клиенты без заказов
3 способа: NOT EXISTS, LEFT JOIN ... WHERE IS NULL, NOT IN. NOT IN + NULL ломается — даёт пустой результат.
Шаг 3: Self-join — иерархия сотрудников
Найти manager-employee pairs. Подвох — отсечь NULL-managers (CEO).
Шаг 4: Cross-join осознанно vs случайно
Случайный CROSS JOIN (забыл ON) на 1M × 1M = катастрофа. Осознанный — генерация календаря × продукты × склады.
Шаги 5-10: JOIN fan-out, multi-table JOIN, NATURAL JOIN, USING vs ON, LATERAL JOIN
Блок 2: Оконные функции — тестируют senior (вопросы 11-20)
Шаг 11: ROW_NUMBER vs RANK vs DENSE_RANK
-- Третий по зарплате в каждом отделе
SELECT * FROM (
SELECT *,
DENSE_RANK() OVER (PARTITION BY dept ORDER BY salary DESC) AS rk
FROM employees
) sub WHERE rk = 3;
Подвох: при равных зарплатах ROW_NUMBER выберет одну строку, DENSE_RANK — несколько.
Шаг 12: LAG / LEAD — MoM, YoY
SELECT month, revenue,
LAG(revenue) OVER (ORDER BY month) AS prev_month,
100.0 * (revenue - LAG(revenue) OVER (ORDER BY month))
/ NULLIF(LAG(revenue) OVER (ORDER BY month), 0) AS mom_pct
FROM monthly_revenue;
Шаг 13: Running total + Moving average
SELECT date, amount,
SUM(amount) OVER (ORDER BY date) AS running_total,
AVG(amount) OVER (ORDER BY date ROWS BETWEEN 6 PRECEDING AND CURRENT ROW) AS ma_7d
FROM transactions;
Шаг 14: ROWS vs RANGE vs GROUPS
Топ-вопрос от senior-интервьюеров. ROWS — физические строки, RANGE — по значениям. На дубликатах ORDER BY поведение разное.
Глубокий гайд по window frames →
Шаги 15-20: Gaps and islands, sessionization, PERCENTILE_CONT, NTILE, CUME_DIST, QUALIFY
Блок 3: CTE и подзапросы (вопросы 21-30)
Шаг 21: CTE vs subquery — когда что
PostgreSQL 12+ inline-ит CTE по умолчанию (то же что subquery). До 12 был optimization fence.
Шаг 22: Recursive CTE — иерархия комментариев
WITH RECURSIVE comments_tree AS (
SELECT id, parent_id, body, 1 AS depth FROM comments WHERE parent_id IS NULL
UNION ALL
SELECT c.id, c.parent_id, c.body, t.depth + 1
FROM comments c JOIN comments_tree t ON c.parent_id = t.id
)
SELECT * FROM comments_tree;
Подвох: infinite loop при циклических данных → WHERE depth < 100.
Шаг 23: Cohort retention через CTE
Шаги 24-30: Funnel analysis, RFM сегментация, top-N per group, EXISTS vs IN, EXCEPT/INTERSECT
Блок 4: Оптимизация и EXPLAIN (вопросы 31-40)
Шаг 31: EXPLAIN ANALYZE BUFFERS
Senior-вопрос — читать план PostgreSQL. Seq Scan на большой таблице с малой selectivity — нужен индекс.
Шаг 32: Sargable vs non-sargable
-- Non-sargable (функция на колонке → seq scan)
WHERE LOWER(email) = 'a@x.com'
-- Sargable (использует индекс или expression index)
WHERE email = 'a@x.com'
-- или CREATE INDEX ON users(LOWER(email));
Шаг 33: Partial / Expression / Covering indexes
Шаг 34: Когда WITH MATERIALIZED полезен
Шаги 35-40: Window function vs GROUP BY perf, dedup стратегии, COUNT(*) vs COUNT(col), pg_stat_statements, lock_timeout
Блок 5: Аналитические задачи (вопросы 41-50)
Шаг 41: Когортный retention
Шаг 42: Воронка с условным dropoff
Шаг 43: ABC-анализ через CUME_DIST
Шаг 44: RFM-сегментация
Шаг 45: LTV расчёт когортный
Шаг 46: Sessionization (30-min gap)
Шаг 47: Customer journey (multi-touch attribution)
Шаг 48: A/B test SQL: SRM check + conversion comparison
Шаг 49: NULL-safe сравнение между source и target
Шаг 50: Pivot через FILTER / crosstab
FAQ
Какие компании самые «жёсткие» на SQL?
Yandex, Tinkoff, Avito — рейтинг по сложности. Senior-вопросы про CTE materialization, EXPLAIN, расы транзакций.
Сколько готовиться к собесу?
Junior без опыта — 1-2 месяца ежедневной практики. Middle с опытом — 2-3 недели на освежить. Senior — глубже теории + system design.
Где тренироваться?
SQL-тренажёр — 491+ задач с PostgreSQL и SQLite в браузере. Проверка результата автоматическая, моментальный feedback.
Что выучить если время поджимает?
Топ-5 priority: JOIN-ы (особенно LEFT + WHERE подвох), window functions (ROW_NUMBER, LAG), CTE и recursive, GROUP BY + HAVING, EXPLAIN основы.
Как обрабатывать вопросы которые не знаю?
«Я бы подумал в направлении X, но не уверен в точном синтаксисе — могу набросать псевдо-код?» — отличный сигнал для интервьюера. Не молчи и не паникуй.
Что дальше
- 🧪 SQL-тренажёр — 491+ задач по всем темам выше
- 🧠 3000+ вопросов с собесов — карточки + квизы для подготовки
- 📚 Window-функции глубокий гайд
- 🔄 JOIN — все типы примеров
- 📈 Cohort retention SQL
- 🚀 ClickHouse гайд
- 📊 10 SQL антипаттернов
Источники
- postgresql.org/docs — официальная документация PostgreSQL
- use-the-index-luke.com — индексы и performance
- pgexercises.com — англоязычные SQL-упражнения
50 вопросов — это база. После них собеседование становится про продуктовое мышление и алгоритмы. Открой SQL-тренажёр — лучшая инвестиция перед собесом.