MySQL SELECT x FROM WHERE NOT IN(SELECT x FROM b) - 意外结果

时间:2009-06-16 12:24:00

标签: sql mysql

我希望下面第三个查询的结果包含id = 732。它没有。那是为什么?

mysql> SELECT id FROM match ORDER BY id DESC LIMIT 5 ;
+------------+
|         id |
+------------+
|        732 | 
|        730 | 
|        655 | 
|        458 | 
|        456 | 
+------------+
5 rows in set (0.00 sec)

mysql> SELECT id FROM email ORDER BY id DESC LIMIT 5 ;
+------------+
|         id |
+------------+
|        731 | 
|        727 | 
|        725 | 
|        724 | 
|        723 | 
+------------+
5 rows in set (0.00 sec)

mysql> SELECT * FROM match WHERE id NOT IN ( SELECT id FROM email ) ;
Empty set (0.00 sec)

表email.id中有三个NULL条目,match.id中没有NULL条目。

可以在 http://pastebin.ca/1462094

查看完整的表格/查询

4 个答案:

答案 0 :(得分:44)

来自documentation

  

要符合SQL标准,IN不仅会返回NULL,而且如果左侧的表达式为NULL,还会发现NULL列表和列表中的一个表达式是IN

这正是你的情况。

NOT INNULL都返回WHERE,这不是SELECT * FROM match m WHERE NOT EXISTS ( SELECT 1 FROM email e WHERE e.id = m.id ) 子句的可接受条件。

重写您的查询,如下所示:

{{1}}

答案 1 :(得分:38)

...或者如果您真的想使用NOT IN,可以使用

SELECT * FROM match WHERE id NOT IN ( SELECT id FROM email WHERE id IS NOT NULL)

答案 2 :(得分:6)

我对MySQL如何处理空值的细节有点脱节,但这里有两件事要尝试:

SELECT * FROM match WHERE id NOT IN 
    ( SELECT id FROM email WHERE id IS NOT NULL) ;

SELECT
    m.*
FROM
    match m
    LEFT OUTER JOIN email e ON
        m.id = e.id
        AND e.id IS NOT NULL
WHERE
    e.id IS NULL

第二个查询看起来很直观,但它确实是连接条件,然后是where条件。这是连接和where子句不相等的情况。

答案 3 :(得分:-2)

这是一些实际上有意义的SQL:

SELECT m.id FROM match m LEFT JOIN email e ON e.id = m.id WHERE e.id IS NULL

简单总是更好。