Шпаргалка по SQL для аналитика данных: все конструкции, которые реально нужны в работе и на собеседовании — на одной странице. Порядок выполнения запроса, JOIN на диаграммах, GROUP BY и HAVING, оконные функции, работа с NULL и датами — с визуальными схемами и мини-примерами. Сохраняй в закладки и повторяй перед собеседованием.
Эта шпаргалка построена по принципу «минимум текста — максимум структуры»: таблицы, визуальные схемы и короткие примеры. Каждый блок заканчивается ссылкой, где тему можно потренировать на реальных задачах. Если SQL для тебя совсем новый — начни с бесплатного курса «SQL с нуля», а сюда возвращайся как к справочнику.
Порядок выполнения SQL-запроса
Самый частый источник ошибок у новичков: запрос читается сверху вниз, а выполняется — нет. Отсюда классика «почему я не могу использовать алиас из SELECT в WHERE».
| Шаг | Конструкция | Что происходит |
|---|---|---|
| 1 | FROM + JOIN | Собираем исходные таблицы |
| 2 | WHERE | Фильтруем строки (агрегатов ещё нет!) |
| 3 | GROUP BY | Схлопываем строки в группы |
| 4 | HAVING | Фильтруем уже группы |
| 5 | SELECT | Вычисляем выражения и алиасы |
| 6 | ORDER BY | Сортируем результат |
| 7 | LIMIT | Отрезаем нужное число строк |
Запомни два следствия: алиасы из SELECT нельзя использовать в WHERE (шаг 5 позже шага 2), а фильтровать по агрегату можно только в HAVING.
JOIN: соединение таблиц
| JOIN | Что вернёт | Типовой случай |
|---|---|---|
| INNER JOIN | Только совпавшие строки | Заказы с существующими клиентами |
| LEFT JOIN | Всю левую + совпадения из правой | Все клиенты, даже без заказов |
| LEFT JOIN … IS NULL | Строки левой БЕЗ пары в правой | Клиенты, которые ни разу не купили |
| FULL JOIN | Всё из обеих таблиц | Сверка двух источников |
| CROSS JOIN | Каждая с каждой | Календарь × товары для решётки |
-- Клиенты без заказов (anti-join)
SELECT c.name
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.id
WHERE o.id IS NULL;
Подводный камень собеседований — fan-out: если в правой таблице несколько строк на ключ, строки левой задублируются, и SUM посчитает лишнее. Проверяй кардинальность до JOIN. Больше примеров — в гайде по JOIN и задачах тренажёра.
GROUP BY и HAVING
-- Города, где средний чек выше 2000
SELECT city, COUNT(*) AS orders_cnt, AVG(amount) AS avg_check
FROM orders
WHERE status = 'paid' -- строки: до группировки
GROUP BY city
HAVING AVG(amount) > 2000; -- группы: после
| Агрегат | Нюанс |
|---|---|
| COUNT(*) | Считает строки, включая NULL |
| COUNT(col) | Пропускает NULL в col |
| COUNT(DISTINCT col) | Уникальные значения |
| SUM / AVG | Игнорируют NULL (AVG делит на не-NULL!) |
| MIN / MAX | Работают и с датами, и со строками |
Оконные функции
Главная тема SQL-секции на собеседовании аналитика. Окно = агрегат без схлопывания строк.
| Функция | Что делает | Типовая задача |
|---|---|---|
| ROW_NUMBER() | Уникальный номер в группе | Дедупликация, «первый заказ клиента» |
| RANK() / DENSE_RANK() | Ранг с пропусками / без | Топ-N с учётом ничьих |
| LAG() / LEAD() | Значение предыдущей/следующей строки | Рост к прошлому месяцу |
| SUM() OVER (ORDER BY …) | Нарастающий итог | Кумулятивная выручка |
| AVG() OVER (… ROWS 6 PRECEDING) | Скользящее среднее | Сглаживание метрики за 7 дней |
-- Последний заказ каждого клиента
SELECT * FROM (
SELECT o.*,
ROW_NUMBER() OVER (PARTITION BY customer_id ORDER BY created_at DESC) AS rn
FROM orders o
) t
WHERE rn = 1;
Разница ROWS и RANGE, дефолтная рамка окна и почему она коварна — в разборе оконных функций.
NULL: три правила
- NULL ни с чем не равен:
x = NULLвсегда неизвестно, толькоx IS NULL. NOT INсо списком, где есть NULL, вернёт пустой результат — используйNOT EXISTS.COALESCE(x, 0)подставляет значение вместо NULL; в расчётах долей это спасает от «дыр».
Даты
| Задача | PostgreSQL |
|---|---|
| Начало месяца | DATE_TRUNC('month', dt) |
| Вытащить год/день недели | EXTRACT(YEAR FROM dt), EXTRACT(DOW FROM dt) |
| Вчера / неделю назад | CURRENT_DATE - INTERVAL '1 day' / '7 day' |
| Разница дат в днях | dt2::date - dt1::date |
-- Выручка по месяцам
SELECT DATE_TRUNC('month', paid_at) AS month, SUM(amount)
FROM orders
GROUP BY 1
ORDER BY 1;
CTE и подзапросы
WITH monthly AS (
SELECT DATE_TRUNC('month', paid_at) AS month, SUM(amount) AS revenue
FROM orders GROUP BY 1
)
SELECT month, revenue,
LAG(revenue) OVER (ORDER BY month) AS prev_revenue
FROM monthly;
CTE (WITH) делает запрос читаемым: каждый шаг — именованный блок. Цепочка из двух-трёх CTE — стандарт продуктовых задач (когорты, воронки). Рекурсивные CTE для иерархий — отдельная тема, разбор с примерами тут.
Мини-справка: строки и агрегация по условию
| Задача | Конструкция |
|---|---|
| Условный агрегат (pivot) | SUM(CASE WHEN type = 'a' THEN 1 ELSE 0 END) |
| Конкатенация | CONCAT(first_name, ' ', last_name) |
| Подстрока по позиции | SUBSTRING(s FROM 1 FOR 3) |
| Поиск по шаблону | LIKE 'abc%' (регистрозависим), ILIKE — нет |
| Убрать пробелы | TRIM(s) |
Как учить это всё
Шпаргалка помогает вспомнить, но не заменяет практику: конструкции запоминаются руками. Рабочая связка — курс «SQL с нуля» для базы, затем 545 задач в тренажёре с автопроверкой, и перед собеседованием — топ-50 реальных вопросов по SQL.
Частые вопросы
Что учить в SQL для собеседования аналитика в первую очередь?
Порядок по частоте на реальных собеседованиях: JOIN и их подводные камни (fan-out, anti-join), GROUP BY + HAVING, оконные функции (ROW_NUMBER, LAG, нарастающий итог), работа с датами (DATE_TRUNC), CTE. Этого хватает для 80% SQL-секций на позиции джуна и мидла.
Чем отличается WHERE от HAVING?
WHERE фильтрует строки до группировки — агрегатные функции в нём недоступны. HAVING фильтрует уже готовые группы после GROUP BY — именно туда идут условия на COUNT, SUM, AVG. Если условие не использует агрегат, ставь его в WHERE: это дешевле, фильтрация происходит раньше.
Нужно ли учить отличия диалектов SQL — PostgreSQL, MySQL, ClickHouse?
Для собеседования достаточно одного диалекта, в РФ стандарт де-факто — PostgreSQL. Отличия (strftime в SQLite, toStartOfMonth в ClickHouse) уточняются за минуты, когда понимаешь общую логику. Исключение — если в вакансии явно указан ClickHouse: тогда посмотри его особенности агрегации и массивов.
Где практиковать SQL бесплатно?
В SQL-тренажёре первые задачи открыты без регистрации, движок PostgreSQL работает прямо в браузере. Плюс бесплатный курс из 10 частей с практикой в каждой части.