Основы SQL-запросов: вопросы для собеседования (часть 8)
SELECT, FROM, WHERE, ORDER BY, LIMIT — базовый синтаксис SQL, с которого начинается любое собеседование. Кажется простым, но интервьюеры проверяют порядок выполнения клауз, приоритет операторов и понимание DISTINCT. Твёрдое знание основ — фундамент, без которого сложные задачи не решить.
Вопросы 36–40 из 40
36В таблице `users` поле `last_login` может быть `NULL` (пользователь ни разу не заходил). Нужно отсортировать пользователей так, чтобы самые недавно заходившие были сверху, а `NULL` значения оказались внизу. Какая сортировка правильная?
A`ORDER BY last_login DESC`
B`ORDER BY last_login DESC NULLS FIRST`
C`ORDER BY last_login ASC NULLS LAST`
D`ORDER BY last_login DESC NULLS LAST`
Ответ: Явно указывайте положение `NULL` в сортировке через `NULLS FIRST` или `NULLS LAST`, чтобы не зависеть от дефолтов.
Нужно два требования: порядок по свежести (это `DESC`) и размещение пропусков внизу (`NULLS LAST`). Поэтому корректно `ORDER BY last_login DESC NULLS LAST`. Если `NULL` не указать явно, поведение может отличаться между СУБД или настройками, а для отчётов и витрин лучше иметь предсказуемый порядок.
37В таблице `events` поле `created_at` имеет тип `timestamp`. Чем отличается фильтр `WHERE created_at >= '2025-03-01'` от `WHERE created_at > '2025-03-01'`?
AОба условия вернут одинаковый результат, потому что дата автоматически приводится к полуночи
BУсловие с `>=` включит события ровно в полночь 1 марта, а условие с `>` их пропустит
CУсловие с `>` включит события ровно в полночь 1 марта, а условие с `>=` их пропустит
DОба условия вызовут ошибку, потому что нельзя сравнивать `timestamp` со строкой даты
Ответ: При сравнении `timestamp` с датой строка `'2025-03-01'` интерпретируется как `'2025-03-01 00:00:00'` — полночь.
Строка `'2025-03-01'` при сравнении с `timestamp` становится `'2025-03-01 00:00:00'`. Оператор `>=` включает события, произошедшие ровно в полночь, а `>` их пропускает. На практике разница обычно невелика, но если система записывает события с точностью до секунды и часть из них попадает ровно на полночь, `>=` захватит их, а `>` — нет.
38Какой набор строк вернёт условие `WHERE is_active = true AND NOT (country = 'RU' AND age > 25)`?
AАктивных пользователей из России старше 25 лет, у которых есть подписка на сервис
BВсех пользователей из России независимо от статуса активности и возраста
CАктивных пользователей не из России или активных пользователей из России от 25 лет и младше
DНеактивных пользователей из России, а также всех пользователей младше 25 лет
Ответ: `NOT` инвертирует выражение в скобках: `NOT (A AND B)` эквивалентно `NOT A OR NOT B` по закону де Моргана.
Условие разбирается так: `is_active = true` — берём только активных. Далее `NOT (country = 'RU' AND age > 25)` по закону де Моргана превращается в `country <> 'RU' OR age <= 25`. Итого: активные пользователи, которые либо не из России, либо из России, но возрастом 25 лет и младше. Пользователь из России с возрастом 30 лет не пройдёт фильтр.
39Что вернёт запрос: `SELECT * FROM orders WHERE CASE WHEN status = 'shipped' THEN created_at > NOW() - INTERVAL '30 days' ELSE amount > 1000 END`?
AЗапрос вернёт все заказы со статусом `'shipped'` за последние 30 дней независимо от суммы заказа
BЗапрос вернёт все заказы с суммой больше 1000 независимо от статуса и даты создания заказа
CЗапрос вернёт ошибку, потому что использовать `CASE WHEN` внутри `WHERE` синтаксически нельзя
DЗапрос вернёт заказы: отправленные за 30 дней или остальные с суммой больше 1000
Ответ: `CASE WHEN` в `WHERE` позволяет применять разные условия фильтрации в зависимости от значений строки.
Для каждой строки `CASE` проверяет статус: если `'shipped'`, применяется условие по дате (последние 30 дней); для остальных статусов — условие по сумме (больше 1000). Это паттерн условной фильтрации: разные строки проходят через разные правила. Такой подход встречается в аналитических запросах, когда логика фильтрации зависит от категории данных.
40Что вернёт запрос `SELECT e.name AS employee, m.name AS manager FROM employees e JOIN employees m ON e.manager_id = m.id`?
AЗапрос вернёт ошибку, потому что нельзя использовать одну таблицу дважды в одном запросе
BЗапрос вернёт всех сотрудников, у которых есть подчинённые, без информации о руководителях
CЗапрос вернёт пары «сотрудник — его руководитель» благодаря псевдонимам `e` и `m`
DЗапрос вернёт каждого сотрудника дважды: один раз как сотрудника и один раз как руководителя
Ответ: Псевдонимы позволяют обращаться к одной таблице как к двум разным источникам в одном запросе.
Здесь таблица `employees` используется дважды: под псевдонимом `e` — как источник сотрудников, под псевдонимом `m` — как источник руководителей. Условие `e.manager_id = m.id` связывает каждого сотрудника с его руководителем. В результате получим пары «сотрудник — руководитель». Сотрудники без руководителя (`manager_id IS NULL`) не попадут в результат при обычном `JOIN`.
Хотите тренировать интерактивно?
В приложении — таймер, прогресс, стрики и 1700+ вопросов по всем темам.
Тренировать в Telegram