Раздел 42 · Аналитика данных с нуля

NULL: пропуски, IS NULL и COALESCE

junior~15 мин

без входаВойди, чтобы отмечать прогресс, вести заметки и решать задачи в редакторе. войти

Бран · продюсер «Хроник Пограничья»

Сколько у нас игроков из России, а сколько из-за рубежа? Мне маркетинг прислал две цифры, сложил их, а до общего числа игроков не хватает пары сотен. Кто-то потерял людей?

Никто людей не терял. Две сотни игроков спрятались в пустых ячейках, и обычные фильтры из урока про WHERE их не видят. Сегодня разбираемся, что такое пустая ячейка в SQL и почему с ней всё не так, как с остальными значениями.

Анкета с пустой графой

Представь стопку бумажных анкет. В графе «Страна» кто-то написал «Казахстан», кто-то «Россия», а кто-то оставил графу пустой. Пустая графа не значит «нет страны» и не значит «Россия». Она значит «мы не знаем».

В базе такая пустая графа называется NULL. NULL это не ноль и не пустая строка ''. Ноль это известное число, пустая строка это известный текст без букв. А NULL это отсутствие знания.

Посмотри на игроков, у которых страна не заполнена:

SELECT id, nickname, country
FROM players
WHERE country IS NULL
LIMIT 3;
 id | nickname    | country
----+-------------+---------
  6 | Velny       | NULL
 12 | sun_rany    | NULL
 17 | raven_ulfen | NULL

Таких игроков в базе 209 из 4092. В нашей песочнице пропуск так и подписан, NULL, чтобы его нельзя было спутать со строкой.

Почему = NULL не работает

Первая мысль новичка: раз ищем пустую страну, напишем country = NULL. Попробуем:

SELECT id, nickname, country
FROM players
WHERE country = NULL;
 id | nickname | country
----+----------+---------
(0 rows)

Ноль строк, хотя только что их было 209. Любое сравнение с неизвестным тоже даёт неизвестное. Спроси себя: «Страна игрока Velny равна неизвестной стране?» Честный ответ: «не знаю». Его SQL и возвращает: NULL.

Получается, у условия в SQL три возможных исхода, а не два: истина, ложь и «неизвестно». Это называется трёхзначной логикой. А WHERE пропускает строку, только если условие истинно. Ложь и «неизвестно» отбрасываются одинаково.

Проверить это можно напрямую, без таблицы:

SELECT NULL = NULL, NULL <> 'RU', 'KZ' <> 'RU';
 ?column? | ?column? | ?column?
----------+----------+----------
 NULL     | NULL     | true

Даже два неизвестных не равны друг другу: две пустые графы не значат, что люди из одной страны.

Для проверки на пропуск в SQL есть отдельные операторы: IS NULL и IS NOT NULL. Они всегда отвечают «да» или «нет», без третьего варианта.

урок из курса

Урок из курса «Аналитика данных с нуля». Курс покупается один раз и остаётся навсегда: 500 ₽.

Оплата пока не подключена: премиум и курсы открываются промокодом.