Выражения и NULL: вопросы для собеседования (часть 2)

NULL в SQL ведёт себя неинтуитивно: NULL = NULL возвращает не TRUE, агрегатные функции игнорируют NULL, а CASE WHEN требует аккуратного обращения с пустыми значениями. Интервьюеры любят задачи-ловушки на тему IS NULL, COALESCE, NULLIF и трёхзначной логики. Непонимание NULL — одна из самых частых ошибок даже у опытных кандидатов.

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

Вопросы 610 из 20

6Что вернёт выражение `COALESCE(NULL, NULL, 'web', 'app')`?
A`NULL`
B`'app'`
C`'web'`
DОшибка, потому что есть `NULL`
Ответ: `COALESCE` возвращает первый аргумент, который не равен `NULL`.

`COALESCE` проверяет аргументы слева направо и возвращает первый не-`NULL`. В выражении `COALESCE(NULL, NULL, 'web', 'app')` первые два аргумента — `NULL`, третий — `'web'`, значит результат будет `'web'`. Это удобно для подстановки значения по умолчанию или для выбора из нескольких потенциальных источников данных.

Подробный разбор →
7В таблице `sessions` 5 строк. Значения `utm_source`: `'google'`, `NULL`, `'email'`, `NULL`, `NULL`. Чему равны `COUNT(*)` и `COUNT(utm_source)`?
A`COUNT(*)` = 2, `COUNT(utm_source)` = 5: первый вариант пропускает `NULL`, второй учитывает все строки
B`COUNT(*)` = 5, `COUNT(utm_source)` = 5: оба варианта считают одинаково и значение `NULL` не влияет на счёт
C`COUNT(*)` = 2, `COUNT(utm_source)` = 2: оба варианта пропускают `NULL` и учитывают только не-`NULL` значения
D`COUNT(*)` = 5, `COUNT(utm_source)` = 2: первый считает все строки, второй пропускает три значения `NULL`
Ответ: `COUNT(*)` считает строки, а `COUNT(column)` считает только не-`NULL` значения в столбце.

`COUNT(*)` считает количество строк, независимо от того, есть ли `NULL` в каких-либо полях. `COUNT(utm_source)` считает количество строк, где `utm_source` не равен `NULL`. В примере всего 5 строк, но только 2 значения не-`NULL` (`'google'` и `'email'`), поэтому получаем `COUNT(*) = 5` и `COUNT(utm_source) = 2`.

Подробный разбор →
8Вы хотите заменить `NULL` в столбце источника перехода на значение `'direct'`. Какой вариант записан корректно и эквивалентен по смыслу?
A`CASE WHEN referrer IS NULL THEN 'direct' ELSE referrer END` и `COALESCE(referrer, 'direct')`
B`CASE WHEN referrer = NULL THEN 'direct' ELSE referrer END` и `COALESCE(referrer, 'direct')`
C`CASE WHEN referrer IS NULL THEN 'direct' ELSE referrer END` и `COALESCE('direct', referrer)`
D`CASE WHEN referrer IS NOT NULL THEN 'direct' ELSE referrer END` и `COALESCE(referrer, 'direct')`
Ответ: `COALESCE(referrer, 'direct')` — короткая запись «если значение `NULL`, подставь значение по умолчанию».

Логика «подставь значение по умолчанию при `NULL`» записывается через `CASE WHEN ... IS NULL`, но `COALESCE(referrer, 'direct')` обычно короче и читабельнее. Запись `referrer = NULL` некорректна и всегда даёт `UNKNOWN` — для проверки на пропуск используют `IS NULL`. Порядок аргументов в `COALESCE` важен: функция возвращает первый не-`NULL` слева направо, поэтому `COALESCE('direct', referrer)` всегда вернёт `'direct'` и не выполнит замену. Условие `IS NOT NULL` тоже меняет смысл — оно подставит `'direct'` именно туда, где значение есть.

Подробный разбор →
9Нужно выбрать заказы, где `delivery_city` не равно `'Moscow'`, но при этом включить строки, где `delivery_city` равен `NULL` (город неизвестен). Какой фильтр корректен?
A`WHERE delivery_city <> 'Moscow'`: обычное сравнение даёт `UNKNOWN` для строк с `NULL` в столбце
B`WHERE delivery_city <> 'Moscow' OR delivery_city IS NULL`: явная проверка `IS NULL` добавит неизвестные значения
C`WHERE delivery_city = 'Moscow' OR delivery_city IS NULL`: оставит только Москву и строки с неизвестным городом
D`WHERE delivery_city != NULL`: попытка сравнить со значением `NULL` через оператор неравенства
Ответ: Чтобы включить строки со значением `NULL`, его нужно проверить явно через `IS NULL`.

Выражение `delivery_city <> 'Moscow'` не вернёт `TRUE` для строк с `delivery_city = NULL` (получится `UNKNOWN`), поэтому такие строки будут исключены. Если по смыслу нужно включить неизвестный город, добавляют явную проверку: `delivery_city IS NULL`. Итоговый устойчивый фильтр: `WHERE delivery_city <> 'Moscow' OR delivery_city IS NULL`.

Подробный разбор →
10В таблице `payments` три строки со значениями `amount`: `NULL`, `NULL`, `NULL`. Что вернут запросы `SELECT SUM(amount)` и `SELECT SUM(COALESCE(amount, 0))`?
AОба запроса вернут `NULL`, потому что `SUM` всегда наследует `NULL` от значений столбца
B`SUM(amount)` вернёт 0, а `SUM(COALESCE(amount, 0))` вернёт `NULL` из-за пустого набора значений
C`SUM(amount)` вернёт `NULL`, а `SUM(COALESCE(amount, 0))` вернёт 0, потому что `COALESCE` заменяет каждый `NULL` на 0
DОба запроса вернут 0, потому что агрегаты на пустых данных по правилам SQL дают 0 по умолчанию
Ответ: Агрегаты пропускают `NULL`, но если все значения `NULL`, `SUM` возвращает `NULL`; `COALESCE` превращает `NULL` в 0 до суммирования.

`SUM` пропускает `NULL`, но если ни одного не-`NULL` значения не нашлось, агрегат возвращает `NULL` — складывать нечего. Если же сначала применить `COALESCE(amount, 0)`, то каждое `NULL` превратится в 0, и сумма станет 0. Это типичный приём для устойчивых метрик, когда отсутствие значения нужно трактовать как ноль. Поэтому два запроса дают разный результат: `NULL` и 0 соответственно.

Подробный разбор →
1234

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

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

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

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

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