По нашей выборке 200+ собесов 2026 — распределение типов задач:
| Тип | Доля задач | Примеры |
|---|---|---|
| Window functions | 40% | ROW_NUMBER для top-N, LAG для MoM |
| JOIN | 25% | INNER vs LEFT, self-join, anti-join |
| Агрегация | 20% | GROUP BY + HAVING + COUNT(DISTINCT) |
| CTE | 10% | Рекурсивные для деревьев |
| Подзапросы | 5% | Correlated subqueries |
Каждая компания имеет специфику задач, основанную на её доменной модели.
| Компания | Топ задачи |
|---|---|
| Яндекс | cohort retention, MoM revenue, sessionization, ABC-анализ |
| Ozon | маркетплейс GMV, take rate, top-K товаров |
| Тинькофф | Vintage, Roll Rates, кредитный scoring |
| Сбер | JOIN на 5+ таблицах, регуляторные отчёты |
| Авито | listing quality, two-sided market, поисковое ранжирование |
| Wildberries | inventory turnover, returns rate, поставщики |
Junior умеет JOIN и базовые окна, Middle понимает window frames и оптимизацию, Senior работает с диалектами и реальными production-объёмами.
| Уровень | Что умеет |
|---|---|
| Junior | JOIN, GROUP BY, ROW_NUMBER, RANK базовые |
| Middle | CTE, window frames (ROWS vs RANGE), EXPLAIN, sargability |
| Senior | Диалекты (PG/CH/Snowflake), индексы, query optimization |
| Lead | Архитектура DWH, partitioning, materialized views |
Эти задачи спрашивают на 80% собесов. Если решаешь их быстро — Middle уровня хватит.
Класс задач: найти непрерывные серии событий (например, дни подряд когда юзер логинился). Магия: разница между date и ROW_NUMBER даёт одинаковую константу для одной серии.
-- Найти серии последовательных дней входа юзера
SELECT
user_id,
MIN(login_date) AS streak_start,
MAX(login_date) AS streak_end,
COUNT(*) AS days_in_row
FROM (
SELECT
user_id,
login_date,
login_date - INTERVAL ROW_NUMBER() OVER (
PARTITION BY user_id ORDER BY login_date
) DAY AS streak_group
FROM logins
) t
GROUP BY user_id, streak_group
HAVING COUNT(*) >= 3
ORDER BY user_id, streak_start;
Сессионизация: разбиение последовательности событий на сессии по таймауту (например, 30 минут неактивности = новая сессия). Используется в продуктовой аналитике для подсчёта DAU/MAU/Average Session Duration.
-- Разбить события на сессии по timeout 30 минут
WITH events_with_gap AS (
SELECT
user_id,
event_ts,
EXTRACT(EPOCH FROM (
event_ts - LAG(event_ts) OVER (PARTITION BY user_id ORDER BY event_ts)
)) / 60 AS minutes_since_prev
FROM events
)
SELECT
user_id,
event_ts,
SUM(CASE WHEN minutes_since_prev > 30 OR minutes_since_prev IS NULL
THEN 1 ELSE 0 END) OVER (
PARTITION BY user_id ORDER BY event_ts
) AS session_id
FROM events_with_gap;
Шпаргалка по window functions — без этого не пройдёшь Middle-собес.
| Функция | Что делает | Пример use case |
|---|---|---|
| ROW_NUMBER() | Уникальный номер строки | Top-N per group |
| RANK() | Ранг с пропусками | Spotify top-10 chart с tie |
| DENSE_RANK() | Ранг без пропусков | Уровни сложности |
| LAG(col, n) | Значение из n строк назад | MoM/WoW сравнения |
| LEAD(col, n) | Значение из n строк вперёд | Прогноз / next event |
| SUM() OVER | Running total | Cumulative revenue |
| AVG() OVER | Moving average | 7-day rolling DAU |
| NTILE(n) | Разбить на n групп | Квартили клиентов |
Эти ошибки автоматически снижают grade. На Senior-собесе их вообще нельзя допускать.
SELECT, FROM, WHERE, ORDER BY, LIMIT, GROUP BY, HAVING, INNER/LEFT JOIN, базовые подзапросы, простые window functions (ROW_NUMBER, RANK). На Junior спрашивают 3-5 задач уровня easy/medium. Достаточно решить 50-100 задач в тренажёре.
PG — реляционная (OLTP), CH — колоночная (OLAP). Спросят: уникальные функции CH (uniq, arrayJoin, MergeTree engine, ASOF JOIN, materialized views, projections), типы данных (LowCardinality, Nullable). PG-задачи: классический SQL + window + CTE.
Класс задач: найти непрерывные «островки» событий (например, дни подряд когда юзер заходил). Решение: window function ROW_NUMBER() + group by (date - row_number = одинаковая константа для группы). Спрашивают на Middle+ собесах в Яндекс/Ozon.
1) Решай 5-10 задач в день в тренажёре. 2) Учи окна (window functions) — топ-1 тема собесов. 3) Разбирай 1-2 query plan в неделю через EXPLAIN ANALYZE. 4) Прокачивай конкретные домены: cohort retention, funnel, RFM. 5) Перед собесом — 3-5 mock-интервью.
Для большинства Junior/Middle позиций — PostgreSQL (стандарт). Для аналитиков в Яндекс, Ozon, Wildberries, Авито — ClickHouse важнее (огромные данные). На собесе обычно дают SQL который работает в обоих диалектах, но могут спросить про CH-специфику.
ROW_NUMBER даёт уникальные номера 1,2,3,4 даже при равных значениях. RANK даёт 1,2,2,4 (с пропуском после tie). DENSE_RANK даёт 1,2,2,3 (без пропуска). На собесе спросят разницу — must know.
В PostgreSQL 12+ CTE и подзапросы оптимизатор обычно сводит в одно и то же (materialized по умолчанию выключен). В старых версиях CTE мог быть materialized → медленнее. Лучше всегда EXPLAIN ANALYZE — никогда не верь интуиции.
Иерархические данные: дерево комментариев, employee → manager, дерево категорий товаров. Также: bill of materials, граф транзакций. Рекурсивный CTE — единственный способ обойти дерево неизвестной глубины без процедурных языков.
SARG = Search ARGument. Sargable выражение в WHERE — позволяет использовать индекс. Например, WHERE date >= "2026-01-01" — sargable, WHERE YEAR(date) = 2026 — нет (функция оборачивает колонку). Спрашивают на Middle+ собесах в bigtech.
UNION удаляет дубликаты (медленный, делает DISTINCT под капотом). UNION ALL — без дедупликации (быстрый). На собесе ловушка: спросят чем отличаются и какой использовать когда. Правильно: UNION ALL если знаешь что дубликатов нет.