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

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

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

Вопросы 1115 из 20

11Есть выражение для маржи: `revenue - cost`. Что получится, если `revenue` = 1000, а `cost` = `NULL`? И какой вариант устойчиво вернёт 1000 при пропущенном `cost`?
AРезультат 1000; устойчивый вариант: оставить выражение `revenue - cost` без изменений и доверять движку
BРезультат `NULL`; устойчивый вариант: явно вычитать неизвестное значение через `revenue - NULL` как маркер
CРезультат 0; устойчивый вариант: обернуть всю разность через `COALESCE(revenue - cost, 0)` после вычисления
DРезультат `NULL`; устойчивый вариант: заменить пропуск нулём заранее через `revenue - COALESCE(cost, 0)`
Ответ: Любая арифметика с `NULL` даёт `NULL`; для подстановки значения по умолчанию используйте `COALESCE` до вычисления.

Если один из операндов в арифметике равен `NULL`, результат всего выражения становится `NULL`, потому что значение «неизвестно» и любая операция с ним тоже неизвестна. Поэтому `revenue - cost` при `cost = NULL` даёт `NULL`, а не 1000. Чтобы трактовать пропущенную себестоимость как 0 (частая аналитическая договорённость), её заменяют до вычитания: `revenue - COALESCE(cost, 0)`. Вариант с `COALESCE(revenue - cost, 0)` маскирует `NULL` нулём только после вычисления, что даёт уже 0, а не 1000 — это другое бизнес-правило.

Подробный разбор →
12Как поведёт себя фильтр `WHERE country IN ('RU', 'KZ')` для строки, где `country IS NULL`?
AСтрока попадёт в результат, потому что `NULL` сравнивается со списком как обычное значение
BСтрока попадёт в результат, если в списке `IN` есть хотя бы два разных значения для проверки
CSQL выдаст ошибку выполнения из-за `NULL` в проверяемом столбце и прервёт запрос целиком
DСтрока не попадёт в результат, потому что выражение даёт `UNKNOWN`, а не `TRUE`
Ответ: При `country IS NULL` выражение `country IN (...)` даёт `UNKNOWN`, поэтому строка не проходит `WHERE`.

`IN` — это набор сравнений на равенство. Если `country` равно `NULL`, то сравнение с каждым элементом (`'RU'`, `'KZ'`) даёт `UNKNOWN`. В итоге всё выражение не становится `TRUE`, и строка не проходит фильтр `WHERE`. Если нужно включать `NULL`, добавляют `OR country IS NULL`.

Подробный разбор →
13В таблице `users` столбец `is_test` может быть 0, 1 или `NULL`. Нужно исключить тестовых пользователей (`is_test` = 1), но оставить остальных, включая `NULL`. Какой фильтр корректен?
A`WHERE is_test <> 1`: одиночное неравенство без отдельной обработки `NULL`-значений поля
B`WHERE is_test = 0`: явный отбор строк с нулевым значением столбца `is_test`
C`WHERE is_test <> 1 OR is_test IS NULL`: неравенство и явная проверка через `IS NULL`
D`WHERE is_test != NULL`: сравнение через оператор неравенства напрямую с `NULL`
Ответ: Условие `<>` исключает строки с `NULL`, если не добавить явную проверку `IS NULL`.

`WHERE is_test <> 1` не пропустит строки с `is_test = NULL`, потому что сравнение даст `UNKNOWN`. Если по смыслу `NULL` означает «неизвестно/не отмечен» и таких пользователей нужно оставить, добавляют `OR is_test IS NULL`. Вариант `WHERE is_test = 0` тоже исключит `NULL`, что меняет смысл выборки. А `is_test != NULL` всегда даёт `UNKNOWN` и не возвращает ничего.

Подробный разбор →
14Нужно посчитать выручку как `price * quantity`, где `quantity` может быть `NULL` (поле не заполнили). По бизнес-правилу пропуск нужно трактовать как 1. Какое выражение корректнее?
A`COALESCE(price * quantity, 1)`: подмена результата на `1` уже после умножения столбцов
B`COALESCE(price, 1) * quantity`: замена цены до умножения на исходный множитель `quantity`
C`CASE WHEN quantity IS NULL THEN 1 ELSE price * quantity END`: при пропуске возвращает `1`
D`price * COALESCE(quantity, 1)`: замена `NULL` в множителе `quantity` до умножения на `price`
Ответ: Если `NULL` в одном из множителей, замените именно его до умножения: `COALESCE(quantity, 1)`.

При `price * quantity` и `quantity = NULL` результат всего выражения будет `NULL`. Корректно заменить именно `quantity` до вычисления: `price * COALESCE(quantity, 1)`. Вариант `COALESCE(price * quantity, 1)` подменяет весь результат и нарушает логику, когда `price` известен. Замена `price` вместо `quantity` не помогает: `NULL` в любом множителе всё равно даст `NULL`.

Подробный разбор →
15В таблице `users` поле `phone` бывает `NULL` и бывает пустой строкой. Какое утверждение верное?
AПустая строка и `NULL` тождественны, и `phone IS NULL` отбирает оба варианта
B`phone IS NOT NULL` оставляет только строки со значением `phone = ''`
C`phone = ''` находит и пустые строки, и `NULL` через неявное приведение типов
D`phone IS NULL` отбирает только `NULL`, а `phone = ''` лишь пустые строки
Ответ: `NULL` и пустая строка — разные значения: `IS NULL` ловит только `NULL`, а `= ''` — только пустую строку.

`NULL` означает отсутствие/неизвестность значения, а пустая строка — это конкретное значение «строка длины 0». Условие `phone IS NULL` выберет только пропуски, а условие `phone = ''` выберет только пустые строки и не вернёт `NULL`, потому что сравнение с `NULL` даёт `UNKNOWN`. Если нужно найти оба варианта, используют, например, `phone IS NULL OR phone = ''`.

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

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

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

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

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

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