我有以下 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);
我注意到查询:
select *
from the_values
where value not in (1,2,3,4,5,6,10);
不返回具有value
NULL 的行,这引起了我的注意。因此,我想知道为什么会这样。我对这种现象的技术方面更感兴趣,而不是明显的解决方案:
select *
from the_values
where value not in (1,2,3,4,5,6,10)
or value IS NULL;
通常,避免任何
NOT IN
NULL
一方都可能涉及值。Postgres Wiki也提出了同样的建议。并避免NOT IN (SELECT ...)
在任何情况下。维基有解释。并且恰好对您的核心问题有完美的答案:这是一个可能不那么明显的解决方案:
或者:
它比您的“显而易见”的更短且通常更快。
对于长列表,请考虑切换到不同(更快)的技术:
如果我们将插入和查询简化为:
对于 null,谓词将评估为:
因此该行不满足谓词。如果您尝试将某些内容与 null 进行比较(将其视为未知),则结果将为 null。
对于 1,谓词将评估为:
因此该行也不满足谓词
即你最终得到一个空的结果