"NOT IN table.col" 和 "NOT IN SELECT col FROM table" 之间的区别

Difference between "NOT IN table.col" and "NOT IN SELECT col FROM table"

一个非常基本的问题。但是

有什么区别
SELECT t.col
FROM table t, other_table o
WHERE t.col NOT IN o.col

SELECT col
FROM table
WHERE col NOT IN (SELECT col FROM other_table)

从语义上讲,这对我来说非常相似,但第一个创建了重复项。我哪里理解错了?

第一个在大多数 RDBMS 中甚至不会 运行,但在 oracle 中它 return 记录的每个组合,除了 t.col = o.col,你如果您将 o.col 添加到您的 SELECT

,就会看到这个

后者查询 table 中的 returns 条记录,这些记录不与 other_table 中的任何记录共享 col 值。

最佳示例:

表 1

| ANIMAL |
|--------|
|    dog |
|    cat |
|  horse |

表 2

| ANIMAL |
|--------|
|    dog |
|   fish |

查询:

SELECT t."animal",o."animal"
FROM Table1 t, Table2 o
WHERE t."animal" NOT IN o."animal"

| ANIMAL | ANIMAL2 |
|--------|---------|
|    cat |     dog |
|  horse |     dog |
|    dog |    fish |
|    cat |    fish |
|  horse |    fish |


SELECT t."animal"
FROM Table1 t
WHERE t."animal" NOT IN (SELECT o."animal" FROM Table2 o)

| ANIMAL |
|--------|
|  horse |
|    cat |

演示:SQL Fiddle

基本上,您在第一个查询中得到了一个笛卡尔积,它将 return 来自两个 table 的记录的每个组合,但是您的 WHERE 条件过滤掉了一个他们中的。第二个查询没有 JOIN、implicit/explicit,它只是从一个 table 中获取记录并根据恰好从另一个 table 中提取的条件进行过滤。

据我所知,查询(稍作修改):

SELECT t.col
FROM table t, other_table o
WHERE t.col <> o.col

生成笛卡尔积,然后对其进行过滤。

下面的示例可能不是发生的确切过程,但它可能提供了对情况的抽象概述。

如果在 table table 中,您将有以下行:

col
----
A
B

并且在 table other_table 中会有:

col
---
B
E
两个 table 查询的

笛卡尔积 (FROM table t, other_table o) 可能是:

table.col     other_table.col
---------------------------
A             B
A             E
B             B
B             E 

然后,应用 WHERE t.col <> o.col 子句过滤上述内容,得到结果

table.col     other_table.col
---------------------------
A             B
A             E
B             E 

由于在查询结果集中,只有table.col个选择输出,最终结果包含A个重复值:

table.col
---------
A        
A        
B        

希望对您有所帮助。

#更新

至于查询:

SELECT col
FROM table
WHERE col NOT IN (SELECT col FROM other_table)

由于没有连接,因此在构建结果时只考虑 table table 中的行集。 据我了解,条件 WHERE col NOT IN (SELECT col FROM other_table) 是针对 table 中的每一行进行评估的。 检查列table.col是否属于从other_table取数据的子查询返回的结果集。如果它验证为 TRUE,则将其纳入结果集中,否则,将其排除在外。

总结一下,我认为第一个查询使 table.col 值加倍只是因为准备阶段,其中 tables 连接(合并)在一起,因此第二个查询需要结果集仅记录来自 table 使用 other_table 仅用于验证目的。这与查询结构有关——当然如果我是对的。