Технические интервью с аналитиками часто теряют структуру: интервьюер задаёт случайные вопросы, оценка субъективна, а сравнивать кандидатов после сложно. Этот список из 10 вопросов даёт чёткую структуру — от базы до продвинутого уровня.
Как пользоваться этим списком
Вопросы разбиты по уровням сложности. Для Junior достаточно вопросов 1–5. Middle должен уверенно отвечать на 1–8. Senior — на все 10.
Оценивайте не только правильность ответа, но и то, как кандидат рассуждает вслух: это показывает реальный уровень понимания.
Вопрос 1: В чём разница между INNER JOIN и LEFT JOIN?
Зачем спрашивать: базовый вопрос, который отсекает тех, кто видел SQL только в туториалах.
Хороший ответ: INNER JOIN возвращает только строки, для которых есть совпадения в обеих таблицах. LEFT JOIN возвращает все строки из левой таблицы, а для строк без совпадения в правой таблице ставит NULL.
-- Все заказы с именем клиента (если клиент удалён — NULL)
SELECT o.id, o.amount, c.name
FROM orders o
LEFT JOIN customers c ON c.id = o.customer_id;
Вопрос 2: Что такое GROUP BY и когда нужен HAVING?
Зачем спрашивать: понимание разницы между фильтрацией строк и фильтрацией групп.
Хороший ответ: GROUP BY группирует строки по значению поля и применяет агрегатные функции. HAVING фильтрует уже готовые группы — его нельзя заменить на WHERE, потому что WHERE выполняется до агрегации.
-- Категории с суммарной выручкой больше 100 000
SELECT category, SUM(revenue) AS total
FROM products
GROUP BY category
HAVING SUM(revenue) > 100000;
Вопрос 3: Как найти дубликаты в таблице?
Зачем спрашивать: практическая задача, которую каждый аналитик решает регулярно.
SELECT email, COUNT(*) AS cnt
FROM users
GROUP BY email
HAVING COUNT(*) > 1;
Вопрос 4: Объясните разницу между подзапросом и CTE
Зачем спрашивать: понимание структуры сложных запросов и заботы о читаемости.
Хороший ответ: оба способа позволяют разбить запрос на части. CTE (WITH ... AS) делает код читаемее, позволяет переиспользовать одну и ту же промежуточную выборку несколько раз, и в некоторых СУБД может кешироваться.
WITH monthly_revenue AS (
SELECT
DATE_TRUNC('month', order_date) AS month,
SUM(amount) AS revenue
FROM orders
GROUP BY 1
)
SELECT month, revenue,
LAG(revenue) OVER (ORDER BY month) AS prev_month
FROM monthly_revenue;
Вопрос 5: Что такое NULL и как с ним работать?
Зачем спрашивать: NULL — источник многих ошибок у начинающих аналитиков.
Хороший ответ: NULL — это не ноль и не пустая строка, а отсутствие значения. Сравнение с NULL через = всегда даёт NULL (неизвестно), нужно использовать IS NULL / IS NOT NULL. Агрегатные функции игнорируют NULL.
Вопрос 6: Напишите запрос с оконной функцией ROW_NUMBER
Зачем спрашивать: оконные функции — маркер Middle-уровня.
-- Первый заказ каждого клиента
SELECT *
FROM (
SELECT *,
ROW_NUMBER() OVER (PARTITION BY customer_id ORDER BY order_date) AS rn
FROM orders
) t
WHERE rn = 1;
Вопрос 7: Как посчитать скользящее среднее за 7 дней?
Зачем спрашивать: типичная аналитическая задача, проверяет знание ROWS/RANGE в оконных функциях.
SELECT
date,
revenue,
AVG(revenue) OVER (
ORDER BY date
ROWS BETWEEN 6 PRECEDING AND CURRENT ROW
) AS rolling_avg_7d
FROM daily_revenue;
Вопрос 8: Что такое индекс и когда он не помогает?
Зачем спрашивать: понимание производительности запросов.
Хороший ответ: индекс ускоряет поиск по полю, строя отдельную структуру данных. Индекс не поможет (или даже замедлит), если: выборка возвращает большую часть строк, применяется функция к индексированной колонке, или СУБД решает, что полный скан дешевле.
Вопрос 9: Объясните разницу между RANK, DENSE_RANK и ROW_NUMBER
Зачем спрашивать: тонкости оконных функций, которые знают только практики.
| Функция | Одинаковые значения | Пропускает позиции |
|---|---|---|
| ROW_NUMBER | разные номера | нет |
| RANK | одинаковые номера | да (1,1,3) |
| DENSE_RANK | одинаковые номера | нет (1,1,2) |
Вопрос 10: Как оптимизировать медленный запрос?
Зачем спрашивать: проверяет системное мышление и опыт работы с реальными данными.
Хороший ответ: начинаю с EXPLAIN ANALYZE, смотрю на Seq Scan по большим таблицам, проверяю наличие индексов на полях в WHERE и JOIN. Затем анализирую структуру запроса: нет ли лишних подзапросов, можно ли упростить CTE.
EXPLAIN ANALYZE
SELECT customer_id, SUM(amount)
FROM orders
WHERE created_at > '2026-01-01'
GROUP BY customer_id;
Как оценивать ответы
Используйте простую шкалу: 0 — не знает, 1 — знает теорию, 2 — может применить на практике. Максимальный балл: 20. Junior — от 8, Middle — от 14, Senior — от 18.
Хотите дать кандидатам возможность подготовиться к техническому интервью? Посоветуйте SQLlab.ru — интерактивные задачи, разобранные по темам именно в таком формате.