我想知道为什么当你在exists子查询中的一个键上连接两个表时,连接必须在WHERE子句而不是FROM子句中发生。
这是我的例子:
加入FROM子句:
SELECT payer_id
FROM Population1
WHERE NOT EXISTS
(Select *
From Population2 join Population1
On Population2.payer_id = Population1.payer_id)
加入WHERE子句:
SELECT payer_id
FROM Population1
WHERE NOT EXISTS
(Select *
From Population2
WHERE Population2.payer_id = Population1.payer_id)
第一个查询给出了0结果,我知道这是不正确的,而第二个查询给出了我期望看到的数千个结果。
有人可以向我解释为什么在EXISTS子查询中发生连接的重要性?如果你在没有父查询的情况下获取子查询并运行它们,它们会给你相同的结果。
在使用存在时,记住不要继续犯这个错误会对我有所帮助。
提前致谢。
答案 0 :(得分:6)
您需要了解常规子查询与相关子查询之间的区别。
使用您的示例,这应该很容易。第一个where
子句是:
where not exists (Select 1
from Population2 join
Population1
on Population2.payer_id = Population1.payer_id
)
这种情况完全它所说的正在做什么。子查询与外部查询没有任何关联。因此,not exists
将过滤掉所有行或保留所有行。
在这种情况下,引擎运行子查询并确定至少返回一行。因此,not exists
在所有情况下都返回false,并且不返回任何内容。
在第二种情况下,子查询是相关子查询。因此,对于population1
中的每一行,子查询都使用Population1.payer_id
的值运行。在某些情况下,Population2
中存在匹配的行;这些被过滤掉了。在其他情况下,匹配的行不存在;这些都在结果集中。
答案 1 :(得分:0)
第一个例子实际上并不是在创建一个不可预测的逻辑的基表上。
执行相同逻辑的另一种方法是:
SELECT payer_id
FROM Population1 P1
LEFT JOIN Population2 P2 ON
P2.Payer_Id = P1.Payer_Id
WHERE
P2.Payer_Id IS NULL
答案 2 :(得分:0)
即使存在一个结果行,您也总是存在返回ROW EXISTS
。
Select *
from Population2
join Population1 on Population2.payer_id = Population1.payer_id
如果此联接中至少存在一行(并且肯定存在),您可以想象您的子目标如下:
select 'ROW EXISTS'
结果:
select *
from Population1
where not exists (select 'ROW EXISTS')
所以你的反半连接回归:
payer_id 1 - >一些ROW EXISTS - >不要返回这一行
payer_id 2 - >一些ROW EXISTS - >不要返回这一行