SQL на собеседовании Junior: базовые и продвинутые вопросы по SELECT, JOIN и GROUP BY
Разбор ключевых вопросов по SQL для начинающих в 2026 году. Практические задачи на JOIN, агрегацию и фильтрацию данных с примерами кода.
Введение: Почему SQL критичен в 2026 году
Несмотря на развитие векторных баз данных и NoSQL-решений, реляционные СУБД (PostgreSQL, MySQL, ClickHouse) составляют основу 82% корпоративных систем хранения данных. Для Junior-разработчика знание SQL — это не просто умение «достать данные», а понимание того, как работает движок базы, как минимизировать нагрузку на диск и как избежать декартова произведения при объединении таблиц. В 2026 году компании стали строже оценивать навыки оптимизации запросов уже на старте, так как объемы данных в типовых проектах выросли в среднем в 4 раза по сравнению с 2022 годом.
Эта статья структурирована как справочник-тренажер. Мы пройдем путь от простейшего извлечения данных до сложных аналитических конструкций. Вы узнаете, чем отличаются разные типы JOIN, почему фильтрация в WHERE работает быстрее, чем в HAVING, и как правильно группировать данные по временным интервалам. Каждая секция содержит теоретический блок, примеры кода и типичные ловушки, которые расставляют интервьюеры.
Для кого этот материал
Материал ориентирован на Junior Backend разработчиков, аналитиков данных и QA-инженеров. Если вы готовитесь к собеседованию в крупные техгиганты или финтех-стартапы, где работа с БД идет через сырые запросы или сложные ORM-вызовы, этот лонгрид поможет систематизировать знания. Мы не будем тратить время на установку СУБД, а сразу перейдем к практике на примере базы данных интернет-магазина с таблицами заказов, клиентов и товаров.
1. Основы SELECT: Больше, чем просто выбор колонок
Команда SELECT — это точка входа в любой запрос. На собеседовании Junior-специалиста часто просят объяснить порядок выполнения операций в SQL (Logical Query Processing). Важно понимать, что SELECT выполняется почти в самом конце, после фильтрации и группировки. Если вы скажете, что база сначала выбирает колонки, а потом их фильтрует — это будет ошибкой. На самом деле порядок таков: FROM -> ON -> JOIN -> WHERE -> GROUP BY -> HAVING -> SELECT -> DISTINCT -> ORDER BY -> LIMIT.
Использование DISTINCT и псевдонимов
Псевдонимы (AS) помогают сделать код читаемым, особенно когда в запросе участвует несколько таблиц с одинаковыми названиями полей. DISTINCT же используется для удаления дублей. Однако опытный интервьюер спросит: «Как DISTINCT влияет на производительность?». Ответ прост: база данных должна отсортировать результат, чтобы найти повторяющиеся строки, что при миллионах записей может замедлить запрос на 30-40%.
-- Выбор уникальных городов клиентов, где заказы были сделаны в 2026 году
SELECT DISTINCT
c.city AS customer_city
FROM
customers AS c
WHERE
c.last_order_date >= '2026-01-01';Вычисляемые поля и конкатенация
Часто требуется объединить имя и фамилию или рассчитать налог прямо в запросе. В разных СУБД синтаксис отличается (в Postgres это ||, в MySQL — функция CONCAT). Умение работать со строковыми функциями — базовый навык. Ниже представлена таблица основных операций в SELECT.
| Операция | Пример синтаксиса (PostgreSQL) | Описание |
|---|---|---|
| Конкатенация | first_name || ' ' || last_name | Объединение строк |
| Математика | price * 0.85 | Расчет цены со скидкой 15% |
| Приведение типов | CAST(total AS INTEGER) | Преобразование типов данных |
| Условия | CASE WHEN price > 1000 THEN 'Premium' ELSE 'Standard' END | Логические ветвления |
2. Фильтрация данных: WHERE против HAVING
Разница между WHERE и HAVING — классический вопрос на 90% собеседований. Основное правило: WHERE фильтрует строки ДО агрегации, а HAVING — ПОСЛЕ. Если вы пытаетесь использовать агрегатную функцию (например, SUM или COUNT) в блоке WHERE, сервер выдаст ошибку. Для Junior важно понимать, почему выгоднее отсекать лишние данные как можно раньше через WHERE, чтобы уменьшить объем данных, попадающих в память для группировки.
Работа с операторами LIKE, IN и BETWEEN
Оператор LIKE используется для поиска по шаблону. Важно помнить про производительность: поиск '%слово%' не использует индексы и приводит к полному сканированию таблицы (Full Table Scan), в то время как 'слово%' может работать эффективно. Оператор IN удобен для проверки вхождения в список, а BETWEEN — для диапазонов дат и чисел, причем границы диапазона в SQL обычно включаются.
-- Поиск активных пользователей из Москвы и Питера с балансом от 500 до 1000
SELECT user_id, email
FROM users
WHERE city IN ('Moscow', 'Saint-Petersburg')
AND balance BETWEEN 500 AND 1000
AND status = 'active';Обработка NULL значений
NULL в SQL — это не ноль и не пустая строка, это «неизвестность». Сравнение value = NULL всегда вернет FALSE. Для работы с неопределенностью используются операторы IS NULL и IS NOT NULL. Также полезно знать функцию COALESCE, которая возвращает первое не-NULL значение из списка — это часто требуется для подстановки дефолтных значений в отчетах.
3. Объединение таблиц: Магия JOIN
JOIN — самая сложная для понимания тема для новичка. В 2026 году данные редко лежат в одной таблице, поэтому умение «сшивать» информацию из разных источников критично. Основные типы: INNER, LEFT, RIGHT и FULL. На собеседовании часто просят нарисовать диаграммы Венна или объяснить, что произойдет, если в правой таблице нет соответствующих записей для левой.
INNER JOIN vs LEFT JOIN
INNER JOIN возвращает только те строки, для которых нашлось совпадение в обеих таблицах. LEFT JOIN возвращает все строки из левой таблицы и дополняет их данными из правой (если совпадений нет, подставляются NULL). В 95% бизнес-задач используется именно LEFT JOIN, например, чтобы вывести список всех клиентов и их заказов (даже если заказов еще не было).
-- Список всех товаров и категорий, к которым они относятся
SELECT
p.product_name,
c.category_name
FROM
products p
INNER JOIN
categories c ON p.category_id = c.id;Self Join и Cross Join
Self Join — это когда таблица объединяется сама с собой. Типичный пример: таблица сотрудников, где в одной колонке указан ID сотрудника, а в другой — ID его начальника. Cross Join (декартово произведение) создает все возможные комбинации строк. В реальности Cross Join используется редко (например, для генерации тестовых данных), и его случайное использование в коде считается грубой ошибкой Junior-разработчика.
4. Агрегатные функции и GROUP BY
Группировка данных позволяет превратить сырые записи в аналитические отчеты. Основные функции: COUNT, SUM, AVG, MIN, MAX. Когда вы используете GROUP BY, все колонки, перечисленные в SELECT (кроме самих агрегатов), обязаны присутствовать в блоке GROUP BY. Это жесткое правило синтаксиса SQL.
COUNT(*) против COUNT(column)
Тонкий вопрос: в чем разница? COUNT(*) считает общее количество строк, включая те, где есть NULL. COUNT(column_name) считает только строки с ненулевыми значениями в этой колонке. На больших таблицах (от 10 млн строк) разница в скорости может быть заметна в зависимости от наличия индексов.
-- Количество заказов и общая сумма по каждому клиенту
SELECT
customer_id,
COUNT(order_id) AS total_orders,
SUM(amount) AS total_spent
FROM
orders
GROUP BY
customer_id
HAVING
SUM(amount) > 5000; -- Фильтруем только крупных покупателейМногоуровневая группировка
Можно группировать данные по нескольким полям сразу, например, по году и категории товара. Это позволяет строить детализированные отчеты. Важно следить за порядком полей: сначала группируем по более общим признакам, затем по частным. В 2026 году для таких задач часто применяют расширения вроде ROLLUP или CUBE, но для Junior достаточно уверенного владения базовым GROUP BY.
5. Подзапросы и обобщенные табличные выражения (CTE)
Когда одного запроса недостаточно, на помощь приходят подзапросы. Они могут быть в блоках SELECT, FROM или WHERE. Однако современным стандартом читаемости кода считаются CTE (Common Table Expressions) с использованием ключевого слова WITH. Они позволяют разбить сложную логику на логические блоки, которые легче отлаживать.
Скалярные и коррелированные подзапросы
Скалярный подзапрос возвращает одно значение (например, среднюю цену по больнице). Коррелированный подзапрос выполняется для каждой строки внешнего запроса, что может катастрофически замедлить работу БД. На собеседовании могут попросить переписать коррелированный подзапрос через JOIN для оптимизации.
-- Использование CTE для поиска клиентов, чьи траты выше среднего
WITH customer_spending AS (
SELECT customer_id, SUM(amount) as total
FROM orders
GROUP BY customer_id
)
SELECT customer_id
FROM customer_spending
WHERE total > (SELECT AVG(total) FROM customer_spending);Преимущества CTE
CTE делают код «плоским» и понятным. В 2026 году использование CTE вместо вложенных подзапросов — признак хорошего тона и зрелости разработчика. Это упрощает код-ревью и позволяет переиспользовать временные результирующие наборы в рамках одного запроса.
6. Сортировка и ограничение выборки (ORDER BY, LIMIT/OFFSET)
ORDER BY позволяет упорядочить данные по возрастанию (ASC) или убыванию (DESC). По умолчанию используется ASC. Важно помнить, что сортировка — ресурсоемкая операция. Если поле не индексировано, базе придется выполнять Full Sort в памяти или на диске.
Пагинация данных
Для Junior-разработчика важно понимать, как реализовать пагинацию (постраничный вывод). Стандартный подход — LIMIT (сколько строк взять) и OFFSET (сколько пропустить). Однако на собеседовании уровня «Junior+» могут спросить про недостатки OFFSET: при больших смещениях база все равно читает все предыдущие строки, что замедляет работу. Альтернатива — «keyset pagination» (фильтрация по последнему ID).
-- Получение второй страницы товаров (по 20 на страницу)
SELECT id, name, price
FROM products
ORDER BY created_at DESC
LIMIT 20 OFFSET 20;Сортировка по нескольким полям
Вы можете сортировать сначала по категории, а внутри категории — по цене. Это помогает структурировать выдачу. Также полезно знать, что можно сортировать по порядковому номеру колонки (например, ORDER BY 2), но в продакшн-коде этого лучше избегать ради читаемости.
7. Работа с датами и временем
В 2026 году работа с часовыми поясами (Timezones) стала еще актуальнее. Базовые функции типа NOW(), DATE_TRUNC или EXTRACT должны быть в арсенале каждого. На собеседовании часто просят посчитать количество регистраций за последнюю неделю или найти пользователей, у которых сегодня день рождения.
Функции извлечения частей даты
Нужно уметь достать год, месяц или день из поля типа TIMESTAMP. В PostgreSQL для этого идеально подходит EXTRACT(MONTH FROM date_column). Также важно понимать разницу между типами DATE (только дата), TIME (только время) и TIMESTAMP (дата и время).
| Задача | Функция (PostgreSQL) | Результат |
|---|---|---|
| Текущее время | NOW() | 2026-05-20 14:30:05 |
| Округление до дня | DATE_TRUNC('day', dt) | 2026-05-20 00:00:00 |
| Разница дат | AGE(date1, date2) | интервал (лет, мес, дней) |
| Добавление времени | dt + INTERVAL '1 day' | завтрашняя дата |
8. Изменение данных: INSERT, UPDATE, DELETE
Хотя Junior чаще пишет SELECT-запросы, понимание DML (Data Manipulation Language) обязательно. Главный страх любого разработчика — UPDATE без WHERE, который обновит все строки в таблице. На интервью могут спросить про транзакции: как гарантировать, что деньги списались с одного счета и точно зачислились на другой.
Безопасное удаление данных
Разница между DELETE и TRUNCATE: DELETE удаляет строки по одной (медленно, но можно откатить и использовать WHERE), TRUNCATE очищает всю таблицу мгновенно (быстро, но обычно не откатывается в рамках простых транзакций и сбрасывает счетчики ID). Также стоит упомянуть Soft Delete — когда мы не удаляем строку физически, а просто ставим флаг is_deleted = true.
-- Безопасное обновление статуса заказа
BEGIN;
UPDATE orders
SET status = 'shipped'
WHERE id = 4521 AND status = 'pending';
COMMIT; -- Применяем изменения только если все окМассовая вставка (Bulk Insert)
Вставлять 1000 записей по одной — плохая практика. Нужно использовать один запрос INSERT INTO ... VALUES (...), (...), .... Это в десятки раз быстрее за счет уменьшения количества сетевых транзакций между приложением и базой данных.
9. Индексы: Как ускорить SELECT
Даже Junior должен знать, что такое индекс. Это как алфавитный указатель в конце книги. Без индекса база делает Full Table Scan. Самый популярный тип индекса — B-Tree. На собеседовании могут спросить: «Почему бы не повесить индексы на все колонки?». Правильный ответ: индексы ускоряют чтение, но замедляют запись (INSERT/UPDATE), так как базе нужно обновлять и саму таблицу, и дерево индекса.
Первичные и внешние ключи
Primary Key (PK) уникально идентифицирует строку и автоматически создает индекс. Foreign Key (FK) обеспечивает ссылочную целостность — вы не сможете удалить категорию, если к ней привязаны товары. Это база проектирования схем данных.
Покрывающие индексы
Если индекс содержит все данные, которые нужны в SELECT, базе даже не нужно лететь к основной таблице — это называется Index Only Scan. Это продвинутая тема, но знание таких нюансов выделяет сильного кандидата на фоне остальных.
10. Операции со множествами: UNION vs UNION ALL
Иногда нужно объединить результаты двух разных запросов в один список. Для этого используются операторы UNION, INTERSECT и EXCEPT. Важное условие: количество и типы колонок в обоих запросах должны совпадать.
В чем разница между UNION и UNION ALL?
UNION убирает дубликаты (выполняет скрытый DISTINCT), что требует ресурсов. UNION ALL просто склеивает результаты «как есть». Если вы уверены, что данные в запросах не пересекаются, всегда используйте UNION ALL — это быстрее. В 2026 году, когда системы часто собирают данные из разных микросервисов, умение эффективно склеивать выборки очень ценится.
-- Объединение списка архивных и активных клиентов
SELECT email FROM active_users
UNION ALL
SELECT email FROM archived_users;11. План выполнения запроса (EXPLAIN)
Если запрос тормозит, нужно посмотреть его «план». Команда EXPLAIN ANALYZE в PostgreSQL показывает, как именно база планирует выполнять ваш код: будет ли она использовать индексы или пойдет сканировать всю таблицу. Junior не обязан уметь читать сложные планы, но должен знать о существовании этого инструмента.
Основные термины плана
- Seq Scan: Последовательное чтение всей таблицы (обычно плохо для больших данных).
- Index Scan: Поиск по индексу (хорошо).
- Nested Loop: Соединение таблиц вложенным циклом (нормально для маленьких наборов).
- Hash Join: Эффективное соединение больших таблиц через хэш-таблицу.
12. Транзакции и уровни изоляции
Транзакция — это логическая единица работы, которая либо выполняется целиком, либо не выполняется вовсе (принцип ACID). На собеседовании Junior-разработчика могут спросить про свойства ACID (Atomicity, Consistency, Isolation, Durability). Понимание того, как база защищает данные от одновременного изменения несколькими пользователями, критично для backend-разработки.
Проблемы параллельного доступа
Грязное чтение (Dirty Read), неповторяющееся чтение и фантомное чтение — это стандартные аномалии, которые возникают, если уровни изоляции настроены неправильно. Большинство СУБД по умолчанию используют уровень Read Committed, который предотвращает чтение незафиксированных данных.
Заключение: План подготовки к SQL интервью
Подготовка к SQL-секции на Junior-позицию в 2026 году должна быть комплексной. Мало просто знать синтаксис, нужно понимать логику работы БД. Начните с основ SELECT, доведите до автоматизма JOIN-ы и обязательно попрактикуйтесь в написании запросов с группировкой.
Чек-лист для самопроверки:
- Я могу объяснить разницу между LEFT JOIN и INNER JOIN на пальцах.
- Я знаю порядок выполнения блоков в SQL запросе.
- Я понимаю, когда использовать WHERE, а когда HAVING.
- Я могу написать CTE для упрощения сложного подзапроса.
- Я понимаю, почему
SELECT *— это плохая практика в продакшене.
Рекомендуемые ресурсы для практики: LeetCode (секция SQL), SQLZoo и интерактивные тренажеры типа StrataScratch. Помните, что на собеседовании важнее показать ход мыслей, чем идеально расставить запятые в коде на доске. Удачи!
Часто задаваемые вопросы
Похожие статьи
Как быстрее вырасти из Junior — стратегии роста зарплаты в 2026 году
Пошаговое руководство по переходу из Junior в Middle. Как увеличить доход в 2 раза за год, освоить AI-инструменты и пройти аттестацию.
Зарплата Junior разработчика в 2026 — реальные цифры по рынку
Сколько платят начинающим программистам в 2026 году. Анализ зарплат по стекам, регионам и форматам работы. Реальные цифры Junior-рынка.
Data Scientist vs Data Analyst в 2026 году: разница в зарплатах, стеке и задачах
Подробное сравнение Data Scientist и Data Analyst в 2026 году. Глубокий разбор зарплат, требований к ML и аналитике, перспектив рынка и AI-инструментария.
Зарплата Python разработчика по грейдам в 2026 году: Junior, Middle, Senior
Подробный разбор рынка Python-разработки в 2026 году. Статистика зарплат по грейдам, влияние AI на стек и требования работодателей.
Красные флаги на HR-скрининге: что насторожит рекрутера в 2026 году
Разбор 12 критических ошибок на первичном интервью. Статистика отказов, психология рекрутинга и чек-листы для подготовки в 2026 году.