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 оставьте для списков, в которых точно нет ни одной пустой графы.
Пустой ответ — самая тихая улика из всех. В архиве вы встретите его не раз, и каждый раз он будет означать разное.