50 вопросов по SQL на собеседовании

Базовые (1–15)

1. Чем WHERE отличается от HAVING?

WHERE фильтрует строки до группировки. HAVING — группы после. В WHERE нельзя агрегаты, в HAVING можно.

2. Что быстрее — UNION или UNION ALL?

UNION ALL (не делает dedup). Используйте UNION только если нужна дедупликация.

3. Чем INNER отличается от LEFT JOIN?

INNER — только совпадения. LEFT — все из левой + совпадения справа, для несовпадающих NULL.

4. Что такое DISTINCT?

Убирает дубликаты строк по всем выбранным столбцам.

5. Порядок выполнения SELECT?

FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY → LIMIT.

6. Можно ли использовать алиас из SELECT в WHERE?

Нет — WHERE выполняется до SELECT. Используйте подзапрос или CTE.

7. Что такое NULL?

Отсутствие значения. Любая операция с NULL даёт NULL (кроме IS NULL).

8. Почему COUNT(*) != COUNT(col)?

COUNT(*) считает все строки. COUNT(col) — только не-NULL значения колонки.

9. Чем TRUNCATE отличается от DELETE?

TRUNCATE быстрее, не логирует каждую строку, сбрасывает auto-increment. DELETE транзакционен, с WHERE.

10. Что делает LIMIT?

Ограничивает количество строк результата. Обычно с ORDER BY.

11. Primary Key vs Unique Key?

PK = UNIQUE + NOT NULL + один на таблицу. UNIQUE — несколько, может быть NULL.

12. Что такое Foreign Key?

Ссылка на PK другой таблицы. Обеспечивает ссылочную целостность.

13. SELECT * FROM t WHERE id = NULL — что вернёт?

Ничего (0 строк). Правильно: WHERE id IS NULL.

14. Чем VARCHAR отличается от CHAR?

VARCHAR — переменная длина. CHAR — фиксированная (дополняет пробелами).

15. Что такое CASCADE в FK?

ON DELETE CASCADE — при удалении parent-записи автоматически удаляются child.

JOIN (16–25)

16. Типы JOIN?

INNER, LEFT, RIGHT, FULL OUTER, CROSS, SELF.

17. Что такое CROSS JOIN?

Декартово произведение — каждая строка левой × каждая правой.

18. Когда LEFT JOIN превращается в INNER?

Если условие на правую таблицу — в WHERE (а не в ON).

19. NATURAL JOIN — что это?

JOIN по всем одноимённым столбцам автоматически. В продакшне не используется (опасно).

20. SELF JOIN — зачем?

JOIN таблицы с самой собой: для иерархий, пар записей, сравнения соседних.

21. USING vs ON?

USING — если столбец называется одинаково. ON — для любых условий.

22. Как найти записи в A, которых нет в B?

A LEFT JOIN B ... WHERE B.key IS NULL или NOT EXISTS.

23. NOT IN + NULL — в чём ловушка?

Если подзапрос возвращает NULL — NOT IN даст 0 строк. Используйте NOT EXISTS.

24. Чем EXISTS отличается от IN?

EXISTS возвращает TRUE на первое совпадение. IN может сравнивать со всем списком.

25. FULL OUTER JOIN — когда нужен?

Для сверки двух источников, когда нужны все строки с обеих сторон.

Оконные функции (26–35)

26. Что такое оконная функция?

Функция, вычисляемая на «окне» строк без свёртки. OVER (PARTITION BY ... ORDER BY ...).

27. Чем ROW_NUMBER отличается от RANK?

ROW_NUMBER всегда уникален (1,2,3). RANK при дублях — одинаковый, с пропуском (1,1,3). DENSE_RANK без пропуска (1,1,2).

28. Что делает LAG?

Возвращает значение из предыдущей строки окна.

29. Как считать нарастающий итог?

SUM(x) OVER (ORDER BY date) — идёт от начала до текущей строки.

30. ROWS BETWEEN — зачем?

Определяет рамку окна для агрегатов (скользящее среднее).

31. Что такое PARTITION BY?

Делит строки на группы для оконных функций. Аналог GROUP BY, но без свёртки.

32. RANGE vs ROWS?

ROWS — физические строки. RANGE — по значениям ORDER BY (включает дубли).

33. Почему нельзя оконную функцию в WHERE?

Оконные вычисляются после WHERE. Обернуть в CTE и фильтровать снаружи.

34. Топ-3 в каждой группе — как?

SELECT * FROM (
  SELECT *, ROW_NUMBER() OVER (PARTITION BY g ORDER BY x DESC) AS rn FROM t
) t WHERE rn <= 3;

35. Что такое FIRST_VALUE / LAST_VALUE?

Первое / последнее значение окна. Осторожно с LAST_VALUE — нужен ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING.

Попробовать силы на подобных вопросах проще всего в тренажёре Карьерник — прямо в Telegram, без регистрации через сайт.

GROUP BY и агрегаты (36–42)

36. Все столбцы SELECT должны быть в GROUP BY?

Да, если они не внутри агрегата.

37. Как посчитать медиану?

PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY x) в PostgreSQL.

38. FILTER WHERE vs CASE WHEN?

FILTER — новый стандарт, чище. CASE WHEN — работает везде.

39. Как посчитать долю в группе?

SELECT x, COUNT(*) * 1.0 / SUM(COUNT(*)) OVER () AS share FROM t GROUP BY x;

40. GROUPING SETS — что это?

Несколько уровней группировки в одном запросе.

41. ROLLUP и CUBE?

ROLLUP — иерархические итоги. CUBE — все комбинации подмножеств.

42. COUNT(DISTINCT x) на 100M строк — быстро?

Нет. Нужен approximate count (uniqCombined в ClickHouse, APPROX_COUNT_DISTINCT в BigQuery).

CTE и подзапросы (43–47)

43. CTE vs подзапрос?

CTE читабельнее, переиспользуемо в запросе. Подзапрос — компактнее, одноразовый.

44. Рекурсивный CTE — зачем?

Иерархии (менеджер → подчинённые), генерация календаря, графы.

45. Материализуется ли CTE?

В PostgreSQL до 12 — всегда. С 13+ — оптимизатор сам решает. В ClickHouse — inline.

46. Коррелированный подзапрос — что это?

Подзапрос, ссылающийся на внешнюю таблицу. Выполняется для каждой строки.

47. Как ускорить коррелированный подзапрос?

Заменить на оконную функцию или JOIN с агрегатом.

Оптимизация (48–50)

48. Как ускорить медленный запрос?

EXPLAIN → искать Seq Scan → добавить индекс. Или переписать без функций на индексированных столбцах.

49. Композитный индекс (a, b, c) работает для WHERE b = 1?

Нет. Только для leftmost prefix: (a), (a, b), (a, b, c).

50. Seq Scan vs Index Scan?

Seq Scan — полный перебор. Index Scan — через индекс. Smart для больших таблиц + узкий фильтр.


Пройти 30–50 задач по теме за вечер можно в Telegram-тренажёре. Это то, что отличает «знаю» от «уверенно отвечу на собесе».

Как готовиться

Проработайте эти 50 вопросов вслух — через неделю они «в пальцах». Для глубокого — решайте задачи.

Читайте также

FAQ

Хватит ли этих 50 для junior?

Да, на 80%. Остальное — практические задачи.

Что добавить для middle?

CUPED, session analysis, оптимизация на больших данных, ClickHouse specifics.

Реально ли спрашивают все 50?

Нет. Обычно 5–10 из этих + 2–3 задачи. Знание всех даёт уверенность.

Как быстро повторить перед собесом?

За 2 часа по этой статье — повторить все ответы вслух. Плюс 3-5 SQL-задач.