SQL 查询的 NULL NOT IN (Empty_Relation) 在不同的引擎上显示不同的行为

NULL NOT IN (Empty_Relation) of SQL query shows different behaviors on different engines

我在 Postrgresql、Spark 上尝试了一个测试 NULL NOT IN Empty_Relation 的查询,我得到了不同的结果。

select count(*) from
(select 1)
where null not in
(a empty relation)

Postgresql 输出 1。 其他输出 0.

我理解 NOT IN 的 NULL 行为,但是我的子查询是空关系,这种情况似乎更有趣。 有很多讨论 NOT IN 的帖子,但我没有找到任何与 NOT IN Empty_Relation.

相关的内容

所以我的问题更像是 ANSI SQL 是否定义了这种行为,或者这实际上是一个灰色区域,两个答案都可以接受。

我很确定 Postgres 是正确的。

虽然几乎每一次与NULLreturnsNULL的比较,你都发现了一个例外。如果集合为空,则集合中没有 nothing。也就是说,无论值如何,任何值 都不在集合中。

请记住,NULL 的语义意味着 "unknown" 值 -- 不是 缺失值。 "Unknown" 表示它可以取任何值。无论 <anything>.

的值如何,表达式 <anything> not in (<empty set>) 都为真

顺便说一下,Postgres 并不是唯一有这种行为的。粗略地看一下 SQL Server 和 Oracle 也 return 1 用于等效查询。

tl;dr:PostgreSQL 是正确的。

这是 SQL 规范对这种行为的描述:

4) The expression RVC NOT IN IPV is equivalent to NOT ( RVC IN IPV )

5) The expression RVC IN IPV is equivalent to RVC = ANY IPV

所以,NULL NOT IN (<empty relation>) 等同于 NOT (NULL = ANY (<empty relation>))

然后,它继续说:

The result of R <comp op> <quantifier> T is derived by the application of the implied <comparison predicate> R <comp op> RT to every row RT in T.

[...]

d) If T is empty or if the implied <comparison predicate> is False for every row RT in T, then R <comp op> <some> T is False.

(注意:<some>ANYSOME -- 它们的意思相同)。

按此规则,由于T为空,NULL = ANY (<empty>)为False,所以NOT (NULL = ANY (<empty relation>)为True。