0Pricing
Coding Interview Prep · Урок

Трёхзначная логика и UNKNOWN

Узнайте, почему NULL = NULL не является истинным и как UNKNOWN распространяется по условиям.

«Трёхзначная логика и UNKNOWN» — бесплатный урок Coding Interview Prep на CoddyKit. Это урок 1 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Coding Interview Prep, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Coding Interview Prep содержит 4 уроков всего.

Почему NULL сбивает кандидатов

NULL — главная причина неправильных ответов на собеседованиях по SQL. Ловушка заключается в том, что его принимают за обычное значение, хотя на самом деле NULL означает «неизвестно» или «отсутствует», а не ноль и не пустую строку.

На собеседованиях любят этот вопрос, потому что синтаксис выглядит правильным, но результат оказывается незаметно неверным. Вам могут показать фильтр, который «должен» вернуть строку, и спросить, почему он ничего не возвращает.

В этом уроке Вы сформируете модель мышления, которая поможет ответить на любой вопрос о NULL: трёхзначную логику. Как только Вы поймёте, что сравнения могут возвращать TRUE, FALSE или UNKNOWN, всё остальное станет очевидным.

NULL — не значение

Самая важная фраза, которую стоит сказать на собеседовании: NULL — это отсутствие значения, а не самостоятельное значение.

Поэтому его нельзя сравнивать с помощью = так же, как числа. База данных не знает, равны ли два неизвестных значения, и поэтому не может однозначно выбрать между TRUE и FALSE.

  • NULL = 5 — это не FALSE, а UNKNOWN
  • NULL = NULL — это не TRUE, а UNKNOWN
  • NULL <> NULL также даёт UNKNOWN

Именно поэтому наивный фильтр равенства по столбцу, допускающему NULL, незаметно исключает строки.

Двухзначная и трёхзначная логика

В большинстве языков программирования используется двухзначная логика: выражение бывает либо TRUE, либо FALSE. SQL добавляет третий результат — UNKNOWN, когда в сравнении участвует NULL.

Таким образом, любое условие в SQL может вычисляться в один из трёх результатов: TRUE, FALSE или UNKNOWN. Предложение WHERE сохраняет строку только тогда, когда её условие даёт ровно TRUE. Для фильтрации UNKNOWN ведёт себя как FALSE, но с точки зрения логики это не одно и то же.

На собеседованиях проверяют, знаете ли Вы это различие, потому что под действием NOT UNKNOWN ведёт себя не так, как FALSE.

Фильтр, который незаметно исключает строки

Рассмотрим классический пример с разбором. Предположим, что bonus иногда имеет значение NULL. Рекрутер спрашивает: «Этот запрос должен вернуть всех, чей бонус не равен 1000. Почему он пропускает сотрудников без бонуса?»

Для строки, где bonus равен NULL, выражение bonus <> 1000 вычисляется как UNKNOWN, а не TRUE. WHERE сохраняет только строки со значением TRUE, поэтому такие сотрудники исчезают из результата.

Исправление заключается в явной обработке NULL, которую мы рассмотрим в следующем уроке. А пока важно понять: пропавшие строки — это результат работы логики, а не ошибка.

SELECT name, bonus
FROM employees
WHERE bonus <> 1000;
-- Rows where bonus IS NULL are excluded:
-- NULL <> 1000 evaluates to UNKNOWN, not TRUE

NULL в выражениях AND

Трёхзначная логика меняет поведение AND. Запомните это правило — и Вы сможете сразу ответить на любой вопрос по таблице истинности.

  • TRUE AND UNKNOWN = UNKNOWN
  • FALSE AND UNKNOWN = FALSE
  • UNKNOWN AND UNKNOWN = UNKNOWN

Логика такова: AND достаточно одного FALSE, чтобы результат был однозначно FALSE. Поэтому FALSE AND что угодно остаётся FALSE. Но TRUE AND неизвестное значение по-прежнему даёт неизвестный результат, поскольку неизвестная сторона может оказаться как TRUE, так и FALSE.

-- If status = 'active' is TRUE but bonus = 100 is UNKNOWN:
SELECT *
FROM employees
WHERE status = 'active' AND bonus = 100;
-- Combined result is UNKNOWN, so the row is NOT returned

NULL в выражениях OR

OR работает зеркально по отношению к AND. Ему достаточно одного TRUE, чтобы результат был однозначно TRUE, поэтому TRUE устраняет влияние UNKNOWN.

  • TRUE OR UNKNOWN = TRUE
  • FALSE OR UNKNOWN = UNKNOWN
  • UNKNOWN OR UNKNOWN = UNKNOWN

Таким образом, строка всё ещё может соответствовать условию с OR, даже если одна ветвь даёт неизвестный результат, при условии что другая ветвь действительно даёт TRUE. Это частый дополнительный вопрос после задачи про AND.

SELECT *
FROM employees
WHERE department = 'Sales' OR bonus = 100;
-- A Sales employee with NULL bonus:
-- TRUE OR UNKNOWN = TRUE, so the row IS returned

NOT меняет TRUE и FALSE, но не UNKNOWN

Это тонкий момент, который интервьюеры обычно оставляют напоследок. NOT превращает TRUE в FALSE, а FALSE — в TRUE, но NOT UNKNOWN по-прежнему даёт UNKNOWN.

Именно поэтому нельзя просто обернуть не сработавшее условие в NOT, чтобы изменить результат. Если для строки с NULL выражение bonus = 1000 даёт UNKNOWN, то NOT (bonus = 1000) тоже даёт UNKNOWN, и строка по-прежнему исключается.

Отрицание не возвращает строки с NULL. Для этого нужна явная проверка IS NULL.

-- For a row where bonus IS NULL:
--   bonus = 1000        -> UNKNOWN
--   NOT (bonus = 1000)  -> UNKNOWN  (still excluded)
SELECT * FROM employees WHERE NOT (bonus = 1000);

Разобранный пример: ловушка NOT IN

Это одна из самых популярных задач о NULL. NOT IN со списком, содержащим NULL, не возвращает ни одной строки, что удивляет кандидатов, ожидающих, что NULL просто будет пропущен.

Внутри x NOT IN (1, 2, NULL) раскрывается в x <> 1 AND x <> 2 AND x <> NULL. Последнее сравнение даёт UNKNOWN, а TRUE AND TRUE AND UNKNOWN сводится к UNKNOWN, поэтому ни одна строка не проходит фильтр.

Безопасная альтернатива — NOT EXISTS, которая не подвержена этой проблеме.

-- Returns ZERO rows if the subquery yields any NULL
SELECT name
FROM employees
WHERE manager_id NOT IN (SELECT manager_id FROM managers);

-- Each comparison against NULL becomes UNKNOWN,
-- and the AND-chain collapses to UNKNOWN for every row.

Почему UNKNOWN ведёт себя как FALSE в WHERE

Частый дополнительный вопрос: «Если UNKNOWN — это не FALSE, почему строка исключается так же, как строка со значением FALSE?»

Ответ точен: WHERE, ON и HAVING используют правило «оставлять только TRUE». И FALSE, и UNKNOWN не проходят эту проверку, поэтому при фильтрации они выглядят одинаково.

Различие проявляется только при отрицании и в ограничениях CHECK. Ограничение CHECK пропускает строку, если условие даёт TRUE или UNKNOWN, поэтому NULL может пройти проверку CHECK, которая, как Вы предполагали, должна была его заблокировать.

-- CHECK passes on TRUE or UNKNOWN, so NULL salary is allowed:
-- CONSTRAINT salary_positive CHECK (salary > 0)
-- INSERT ... salary = NULL  -> NULL > 0 is UNKNOWN -> allowed

Более глубокий пример: COUNT и пробел в логике истинности

Свяжем всё это с реалистичной формулировкой с собеседования. «У нас 100 сотрудников. SELECT COUNT(*) WHERE bonus = 100 возвращает 30, а WHERE bonus <> 100 — 50. Куда делись остальные 20?»

У 20 пропавших сотрудников бонус имеет значение NULL. Ни = 100, ни <> 100 не дают для них TRUE — оба выражения дают UNKNOWN, поэтому эти строки не проходят ни один из фильтров.

Фраза «категории не дают в сумме общее количество, потому что NULL не удовлетворяет ни одному из условий» — именно тот ответ, который хотят услышать на собеседовании.

SELECT
  COUNT(*) FILTER (WHERE bonus = 100)  AS eq_100,
  COUNT(*) FILTER (WHERE bonus <> 100) AS ne_100,
  COUNT(*) FILTER (WHERE bonus IS NULL) AS null_bonus,
  COUNT(*) AS total
FROM employees;

Что сказать на собеседовании

Когда речь заходит о логике NULL, упомяните следующие моменты, чтобы продемонстрировать высокий уровень:

  • NULL означает неизвестное значение; сравнения с ним дают UNKNOWN.
  • SQL использует трёхзначную логику: TRUE, FALSE, UNKNOWN.
  • WHERE, ON и HAVING сохраняют только TRUE-строки.
  • NOT UNKNOWN по-прежнему даёт UNKNOWN, поэтому отрицание не возвращает строки с NULL.
  • NOT IN с любым NULL не возвращает строк; предпочитайте NOT EXISTS.

Сначала изложите модель, а затем пройдите по таблице истинности. Такой порядок показывает, что Вы понимаете причину, а не просто запомнили приём.

Быстрая проверка

Проверьте, насколько хорошо Вы понимаете трёхзначную логику.

Итоги

Теперь у Вас есть ключевая модель мышления о NULL:

  • NULL — это неизвестное значение, а не значение; никогда не сравнивайте его с помощью = или <>.
  • SQL использует трёхзначную логику: условия возвращают TRUE, FALSE или UNKNOWN.
  • Условия фильтрации сохраняют только TRUE; строки с UNKNOWN исчезают так же, как строки с FALSE.
  • NOT меняет TRUE на FALSE и FALSE на TRUE, но оставляет UNKNOWN без изменений.
  • Ловушка NOT IN + NULL возвращает ноль строк; используйте NOT EXISTS.

Далее Вы узнаете, как правильно проверять NULL с помощью IS NULL, IS NOT NULL и операторов сравнения с безопасной обработкой NULL.

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

Урок «Трёхзначная логика и UNKNOWN» бесплатный?

Да — полный текст урока «Трёхзначная логика и UNKNOWN» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Coding Interview Prep, подпишись на CoddyKit PRO. Курс Coding Interview Prep содержит 4 уроков всего.

Чему я научусь в уроке «Трёхзначная логика и UNKNOWN»?

Узнайте, почему NULL = NULL не является истинным и как UNKNOWN распространяется по условиям. Ты практикуешь Coding Interview Prep с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Coding Interview Prep?

Предыдущий опыт не требуется. Coding Interview Prep на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 1 из 4.

Сколько времени занимает урок «Трёхзначная логика и UNKNOWN»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Coding Interview Prep?

Да. Каждый урок Coding Interview Prep включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Трёхзначная логика и UNKNOWN
  2. IS NULL, IS NOT NULL и безопасное сравнение с NULL
  3. COALESCE, NULLIF и ISNULL
  4. NULL в агрегатах, объединениях и DISTINCT
← Назад к Coding Interview Prep