为什么不总是在Oracle中检索与MINUS相同的结果?

时间:2014-08-28 01:45:30

标签: sql oracle

我有两张桌子:

CREATE TABLE test1
(id int);

CREATE TABLE test2
(id int);

INSERT INTO test1
VALUES (1);

INSERT INTO test1
VALUES (2);

INSERT INTO test2
VALUES (1);

然后我想查看test1中所有id的列表,而不是test2中的。

我至少有三种方法可以做到这一点:

外部加入

SELECT a.id
FROM test1 a LEFT OUTER JOIN test2 b 
ON a.id = b.id
WHERE b.id IS NULL;

MINUS

SELECT id
FROM test1
MINUS
SELECT id
FROM test2;

不在

SELECT id
FROM test1
WHERE id NOT IN (
                 SELECT id 
                 FROM test2
                );

到目前为止,这么好。所有这三个查询都应该给我相同的结果:1行,值为2.

如果我在test2中插入一个null,那么OUTER JOIN和MINUS查询将继续返回相同的结果,但NOT IN不会返回任何行。

这让我很困惑。然后我注意到如果我将其改为

SELECT id
FROM test1
WHERE id NOT IN (
                 SELECT id 
                 FROM test2
                 WHERE id IS NOT NULL
                );

我得到了我期待的结果 - 再一行。

为什么会这样?我认为这是SQL非常重要的东西,但是我不清楚它是什么(我很确定在我之前使用过的其他数据库中,我列出的三种方法都给出了相同的结果 - 尽管我不喜欢现在没有SQL Server或postgres进行测试,所以我可能会错误地记录他们的行为。

(我认为对此的一个答案是“不要担心,只是不要使用NOT IN”,但这在代码可读性方面可能很昂贵 - 有时候这比使用外连接或减去所有东西更优雅。)< / p>

1 个答案:

答案 0 :(得分:3)

如果NULL处于NOT IN条件,则结果将始终为NULL

id NOT IN (a, b, c)

与:

相同
id != a AND id != b AND id != c

所有内容都与NULL!=进行比较,结果为NULL,因此结果为空。


id IN (a, b, c)

相同
id = a OR id = b OR id = c

,对吧?

所以!(id = a OR id = b OR id = c)id != a AND id != b AND id != c