Tenho o seguinte script SQL:
CREATE temporary table if not EXISTS the_values (
key SERIAL,
value INTEGER NULL
);
insert into the_values(value) values (null),(1),(null),(2),(3),(4),(5),(6),(10),(null),(null);
select *
from the_values
where value not in (1,2,3,4,5,6,10);
E notei que a consulta:
select *
from the_values
where value not in (1,2,3,4,5,6,10);
Não retorna as linhas com value
NULL, e isso me chamou a atenção. Por isso, quero saber por que isso acontece. Estou interessado mais no aspecto técnico desse fenômeno do que na solução óbvia:
select *
from the_values
where value not in (1,2,3,4,5,6,10)
or value IS NULL;
Geralmente, evite
NOT IN
quandoNULL
os valores podem estar envolvidos em ambos os lados. O Postgres Wiki sugere isso. E eviteNOT IN (SELECT ...)
em qualquer caso. A Wiki tem a explicação. E também tem a resposta perfeita para sua pergunta principal:Aqui está uma solução talvez não tão óbvia:
Ou:
É mais curto e normalmente mais rápido que o seu "óbvio".
Para listas longas , considere mudar para uma técnica diferente (mais rápida):
Se simplificarmos a inserção e a consulta para:
Para null, o predicado será avaliado para:
para que a linha não satisfaça o predicado. Se você tentar comparar algo com null (pense nisso como desconhecido), o resultado será null.
Para 1, o predicado será avaliado para:
para que a linha também não satisfaça o predicado
Ou seja, você acaba com um resultado vazio