我知道这个问题可能回答了太多次,但我找不到发生这种情况的原因。
我有 2 个表,我正在尝试从表 2 中选择表 1 中不存在的行,但是当我运行该查询时,即使我 100% 确定表 1 中有行不在表 2 中,它也没有显示任何结果。我的查询类似于以下内容:
select pid from tbl1 where not exists ( select pid from tbl2)
我知道还有其他方法可以实现这一点,我只是想了解为什么它不起作用的概念。
谢谢。
NOT EXISTS
检查子查询中是否没有行。您的子查询应该是相关的,但由于它不是相关的,它的行为不会像您期望的那样。
实际上,如果您的子查询选择任何行,则不满足条件,并且谓词对所有行都失败。这意味着,您的查询根本不会返回任何行。
查询返回行的唯一情况是表tbl2
为空。
解决方案#1:使用IN
现在,您可以使用此处显示的其他答案的相关子查询,也可以改用IN
(如果tbl2
永远不会有空值)。例如:
select pid from tbl1 where pid not in (select pid from tbl2)
解决方案#2:使用EXCEPT
select pid from tbl1
except
select pid from tbl2
解决方案#3:使用反联接
select a.pid
from tbl1 a
left join tbl2 b on b.pid = a.pid
where b.pid is null
你需要一个相关子句:
select pid
from tbl1
where not exists (select 1 from tbl2 where tbl2.pid = tbl1.pid)
-------------------------------------------^ correlation clause
子查询返回的列无关紧要 - 重要的是它是否返回行。 关联子句执行您想要的操作。 在您的情况下,如果tbl2
有任何行,则子查询返回一行,NOT IN
返回 false。
您可能会将NOT EXISTS
与NOT IN
混淆。 也就是说,我强烈建议使用NOT EXISTS
而不是NOT IN
.
你也可以使用IN
子句,
select pid from tbl1 where pid not in ( select pid from tbl2)
如果要使用exists
则需要定义连接条件
select pid from tbl1 where not exists ( select pid from tbl2 where tbl2.pid = tbl1.pid)