Основы SQL-запросов: вопросы для собеседования (часть 7)

SELECT, FROM, WHERE, ORDER BY, LIMIT — базовый синтаксис SQL, с которого начинается любое собеседование. Кажется простым, но интервьюеры проверяют порядок выполнения клауз, приоритет операторов и понимание DISTINCT. Твёрдое знание основ — фундамент, без которого сложные задачи не решить.

Агрегация, GROUP BY и HAVINGДаты и времяEXPLAIN и оптимизацияВыражения и NULLJOIN и операции множествСтроки и приведение типовПодзапросы и CTEОконные функции

Вопросы 3135 из 40

31В запросе `SELECT u.name FROM users u WHERE EXISTS (SELECT 1 FROM orders o WHERE o.user_id = u.id)` — как работает `EXISTS`?
AПодзапрос в `EXISTS` должен вернуть ровно одну строку, иначе запрос вызовет ошибку выполнения
BПодзапрос в `EXISTS` проверяет наличие хотя бы одной строки: если есть — условие истинно
CПодзапрос в `EXISTS` возвращает список значений, которые используются как фильтр в основном запросе
DПодзапрос в `EXISTS` возвращает количество совпавших строк и сравнивает его с порогом
Ответ: `EXISTS` возвращает `TRUE`, если подзапрос возвращает хотя бы одну строку, иначе — `FALSE`.

`EXISTS` не анализирует конкретные значения из подзапроса — важен сам факт наличия строк. Для каждого пользователя из `users` подзапрос проверяет, есть ли хотя бы один заказ с его `user_id`. Если есть — строка попадает в результат. Именно поэтому в подзапросе часто пишут `SELECT 1` — возвращаемое значение не имеет значения.

32Что вернёт запрос `SELECT name FROM users WHERE id IN (SELECT user_id FROM orders WHERE created_at >= '2025-01-01')`?
AЗапрос вернёт ошибку, потому что подзапрос в `IN` не может ссылаться на другую таблицу
BЗапрос вернёт всех пользователей, потому что подзапрос выполняется отдельно от основного
CЗапрос вернёт только тех пользователей, чей `id` есть хотя бы в одном заказе за 2025 год
DЗапрос вернёт пользователей, у которых все заказы сделаны только в 2025 году
Ответ: Подзапрос в `IN` возвращает набор значений, и основной запрос фильтрует строки по вхождению в этот набор.

Подзапрос `SELECT user_id FROM orders WHERE created_at >= '2025-01-01'` формирует список идентификаторов пользователей, сделавших хотя бы один заказ с начала 2025 года. Затем `WHERE id IN (...)` оставляет только тех пользователей из таблицы `users`, чей `id` входит в этот список. Это стандартный паттерн для фильтрации по связанной таблице.

33В таблице `events` поле `updated_at` может быть `NULL` (ещё не обработано). Нужно отсортировать так: сначала обработанные события по свежести обновления, затем необработанные (`NULL`) внизу, и при одинаковом `updated_at` порядок должен быть стабильным по `event_id`. Какой `ORDER BY` соответствует этому?
A`ORDER BY updated_at DESC NULLS FIRST`
B`ORDER BY updated_at DESC, event_id ASC`
C`ORDER BY updated_at DESC NULLS LAST`
D`ORDER BY updated_at DESC NULLS LAST, event_id ASC`
Ответ: Сочетайте `NULLS LAST` для положения пропусков и второй столбец в `ORDER BY` для стабильности при совпадениях.

Требование «сначала свежие обновления» означает `updated_at DESC`. Требование «`NULL` внизу» означает `NULLS LAST`. Требование стабильности при одинаковом `updated_at` означает добавление tie-breaker, например `event_id ASC`. Поэтому корректная сортировка: `ORDER BY updated_at DESC NULLS LAST, event_id ASC`.

34Маркетинг хочет сначала увидеть пользователей, которые ни разу не заходили (`last_login` = `NULL`), а затем — остальных по возрастанию `last_login` (чем раньше логин, тем выше). Какой `ORDER BY` соответствует этому?
A`ORDER BY last_login DESC NULLS LAST`
B`ORDER BY last_login ASC NULLS LAST`
C`ORDER BY last_login DESC NULLS FIRST`
D`ORDER BY last_login ASC NULLS FIRST`
Ответ: Чтобы `NULL` были сверху, используйте `NULLS FIRST`; направление `ASC`/`DESC` задаёт порядок непустых значений.

Требование «сначала `NULL`» означает `NULLS FIRST`. Требование «остальные по возрастанию даты» означает `ASC`. Поэтому итог: `ORDER BY last_login ASC NULLS FIRST`. Это удобно для списков, где нужно приоритизировать пользователей без активности.

35Вы делаете пагинацию по заказам: `SELECT order_id, created_at FROM orders ORDER BY created_at DESC LIMIT 50 OFFSET 50`. Иногда один и тот же `order_id` встречается на двух страницах. Какое улучшение проще всего сделать в рамках этих же операторов, чтобы порядок был более детерминированным?
AУвеличить `LIMIT` до 100, чтобы реже перелистывать страницы
BУбрать `OFFSET`, оставив только `LIMIT 50`
CДобавить `WHERE created_at IS NOT NULL`, чтобы исключить пропуски
D`ORDER BY created_at DESC, order_id DESC`
Ответ: Добавляйте уникальный tie-breaker в `ORDER BY`, если первый столбец сортировки не уникален.

Если `created_at` повторяется у многих заказов, то порядок строк с одинаковым временем может «плавать». Это особенно заметно при `LIMIT`/`OFFSET`, когда граница страницы проходит внутри группы одинаковых значений. Добавив уникальный столбец в сортировку, например `order_id`, вы фиксируете порядок: `ORDER BY created_at DESC, order_id DESC`. Это не решает всех проблем `OFFSET` при изменяющихся данных, но делает порядок воспроизводимым для одного и того же набора строк.

12345678

Хотите тренировать интерактивно?

В приложении — таймер, прогресс, стрики и 1700+ вопросов по всем темам.

Тренировать в Telegram

Другие темы: SQL

Агрегация, GROUP BY и HAVINGДаты и времяEXPLAIN и оптимизацияВыражения и NULLJOIN и операции множествСтроки и приведение типовПодзапросы и CTEОконные функции