Null和IN()提供意外结果

时间:2011-07-29 14:47:25

标签: sql null matching

这似乎是如此基本,我因为缺乏一个更好的词而大吃一惊。我有两张桌子,我们称之为albumsartists

CREATE TABLE `albums` (
  `album_id` bigint(20) NOT NULL AUTO_INCREMENT,
  `artist_id` bigint(20) DEFAULT NULL,
  `name` varchar(200) NOT NULL,
  PRIMARY KEY (`album_id`)
)
CREATE TABLE `artists` (
  `artist_id` bigint(20) NOT NULL AUTO_INCREMENT,
  `name` varchar(250) NOT NULL,
  PRIMARY KEY (`artist_id`)
)

每个表中有几十万秒。一些专辑行的空artist_id,这是预期的。

但是,当我执行以下查询以查找没有相册的艺术家时:

SELECT * FROM artists WHERE artist_id NOT IN (SELECT artist_id FROM albums)

...查询返回零结果。我知道这不是真的。所以我尝试了这个:

SELECT * FROM artists WHERE artist_id NOT IN (SELECT artist_id FROM albums WHERE artist_id IS NOT NULL)

......我回来了几千行。我的问题是:为什么第一个查询似乎操作任何数字= NULL的想法?或者这是NULL对IN()语句的奇怪影响?我觉得这是我错过的基本内容。我根本不在我的数据库表中使用NULL。

3 个答案:

答案 0 :(得分:7)

快速回答 - IN语句是=a OR =b OR ...的快捷方式。如果在此列表中包含空值,那么我认为这会破坏该语句。你的第二个选择可能是更好的选择。

或者使用联接也可能有效,并且效率更高。

答案 1 :(得分:7)

这就是NOT EXISTS在语义上正确的原因

SELECT * FROM artists ar
WHERE  NOT EXISTS
   (SELECT * FROM albums al WHERE ar.artist_id = al.artist_id)

逻辑:

    实际上是
  • NOT IN (x, y, NULL)
      实际上是
    • NOT (x OR y OR NULL)
      • (NOT x) AND (NOT y) AND (NOT NULL)

因此NULL使整个NOT IN

无效

答案 2 :(得分:2)

它与SQL NULL的解释方式有关 - 你必须将它们视为UNKNOWN值。

假设你有artist_id = 1

如果您运行以下内容:

artist_id = NULL

而不是“假” - 你得到'未知';

当您运行诸如您的查询时,仅返回评估为“TRUE”的值。

artist_id IN (NULL, NULL, NULL...) = UNKNOWN
artist_id NOT IN (NULL, NULL, NULL....) = UNKNOWN
相关问题