Не используйте NOT IN
с подзапросами!Когда подзапрос возвращает значение NULL
, он имеет поведение, которое вы видите.Строки не возвращаются.
По этой причине я настоятельно рекомендую NOT EXISTS
или LEFT JOIN
/ WHERE
.Итак:
select a
from xo
where not exists (select 1 from xo xo2 where xo2.c = xo.a);
Это вернет дополнение:
select a
from xo
where exists (select 1 from xo xo2 where xo2.c = xo.a);
Техническая причина, по которой это происходит, заключается в том, что NULL
является неизвестным значением, а неособая ценностьИтак:
1 in (1, 2, 3) returns TRUE
1 not in (1, 2, 3) returns FALSE
Но:
1 in (1, 2, 3, NULL) returns TRUE, because 1 is explicitly in the list
1 in (2, 3, NULL) returns NULL (equivalent to FALSE) because `NULL` could be 1 or not
И:
1 not in (1, 2, 3, NULL) returns FALSE because 1 is explicitly in the list
1 not in (2, 3, NULL) returns NULL, because 1 could be in the list
Итак, когда любое значение равно NULL
, NOT IN
возвращает либо FALSE, либо NULL
- и, следовательно, все строки отфильтровываются.