NOT IN и NULL: почему запрос всегда пустой

Вам нужны все, кого нет в журнале визитов. Пишете очевидное:

SELECT * FROM contacts
WHERE id NOT IN (SELECT person_id FROM receipts);

Ноль строк. Ни одной. И это подозрительно радует — пока не понимаете, что должно было выйти минимум десять человек.

«Ноль строк — не значит „всех проверили“. Иногда это значит: вопрос сломан, а ошибки об этом никто не скажет.»

Откуда взялся пустой ответ?

Причина — в подзапросе есть хотя бы одна пустая графа person_id. Сравнение с призраком (NULL) не даёт ни ДА, ни НЕТ, только «неизвестно» — и NOT IN, наткнувшись на неизвестное хоть раз, не срабатывает уже никогда, для всей таблицы разом.

Лечение — сменить инструмент, а не подпирать старый проверкой на всякий случай.

SELECT * FROM contacts p
WHERE NOT EXISTS (
  SELECT 1 FROM receipts l WHERE l.person_id = p.id
);
-- NOT EXISTS про NULL не спотыкается вовсе
«NOT IN — бомба с одним NULL внутри подзапроса. NOT EXISTS этой мины не боится.»

Правило на будущее: ищете «у кого нет пары» — берите NOT EXISTS или LEFT JOIN ... IS NULL. NOT IN оставьте для списков, в которых точно нет ни одной пустой графы.

Пустой ответ — самая тихая улика из всех. В архиве вы встретите его не раз, и каждый раз он будет означать разное.

$0
тащи карточки за верхнюю кромку · «+ стикер» · «🧵 нить» — клик по двум

ЛОТОК УЛИК

во вкладке SQL найди подозреваемых и жми «+ доска»

НА ПРОВЕРКУ

теории из «Заметок» отправляются сюда — подтверди на доске или удали
Ctrl+Enter · «+ доска» на строке — выбрать поля и перенестипиши запрос, я подожду
Результат появится здесь.

Картотека

Заметки

Факты

Теории на проверку

Подсказки

◆ РЕЖИМ АРХИВАРИУСАуправление картотекой дел · не виден игроку