ENIGMA AI
ENIGMA AI
SQL и базы данных Разбор 28 мин чтения

SQL на собеседовании Junior: базовые и продвинутые вопросы по SELECT, JOIN и GROUP BY

Разбор ключевых вопросов по SQL для начинающих в 2026 году. Практические задачи на JOIN, агрегацию и фильтрацию данных с примерами кода.

ENIGMA AI -
Вопросы по SQL на собеседовании Junior: SELECT, JOIN, GROUP BY
В 2026 году SQL остается фундаментом для backend-разработки и аналитики. По данным опросов Stack Overflow, 54% Junior-специалистов проваливают технический этап из-за ошибок в логике JOIN и непонимания работы агрегатных функций. В этой статье мы разберем 12 ключевых тем, которые гарантированно встретятся на интервью.

Введение: Почему 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. Помните, что на собеседовании важнее показать ход мыслей, чем идеально расставить запятые в коде на доске. Удачи!

Часто задаваемые вопросы

Поделиться статьей

Похожие статьи