不存在的结果不存在而不存在

时间:2014-11-26 07:29:29

标签: mysql sql subquery

我有两个非常相似的查询,但是它们会返回不同的结果。

第一个:

select * from products p 
where p.val >= 999999 and 
  not exists 
    (select * from products p2 where p2.val < 999999 and p.user_id = p2.user_id);

第二个:

select * from products p
where p.val >= 999999 and
   p.user_id not in (select user_id from products p2 where p2.val < 999999);

第一个给了我正确答案,而第二个给了我没有(零)结果。这可能是因为第二个查询中的子查询产生了太多结果吗?

1 个答案:

答案 0 :(得分:3)

小心无效!

如果子查询中有NULL,则NOT IN将无法像大多数人期望的那样工作。

如果您将NOT IN (...)翻译为NOT (... OR ...)NOT ... AND NOT ...并将three-valued logic应用于生成的表达式,则问题会更加明确。

为了用一个例子来说明这一点,让我们说条件是NOT IN (1, 2, NULL),而被检查的行的值是3。

使用NOT (... OR ...)即可获得此信息:

NOT (3=1 OR 3=2 OR 3=NULL)

括号中的前两个条件为false,最后一个条件未知。基于三值逻辑,析取的结果将是未知的。根据同样的逻辑,未知的倒置也是未知的。 WHERE子句中未知的结果与false的结果相同,即不匹配。所以,你在这里。

现在,如果你用NOT ... AND NOT ...重写NOT IN,这就是你得到的:

NOT 3=1 AND NOT 3=2 AND NOT 3=NULL

前两个术语是真的,最后一个是未知的(3=NULL未知,其反转也是未知的)。同样,三值逻辑表明在这种情况下最终结果是未知的。你又来了。

因此,当一行的值不在子集中但子集也包含空值时,要么不使用NOT IN,要么过滤掉空值。