在“exists”子查询中使用Join

4
我想知道为什么在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子句中的JOIN:

SELECT payer_id
  FROM Population1
  WHERE NOT EXISTS
        (Select *
           From Population2
          WHERE Population2.payer_id = Population1.payer_id)

第一个查询给出了0个结果,我知道这是不正确的,而第二个查询给出了我期望看到的成千上万的结果。
有人能解释一下为什么存在子查询中连接发生的位置很重要吗?如果你将子查询取出并运行,它们实际上会给出相同的结果。
这会帮助我记住在使用exists时不要继续犯这个错误。
提前致谢。

1
第一个查询根本没有意义。所以,您正在将表“Population1”与“Population2”连接,并且您正在说,如果存在任何一行作为该连接的结果,则不要从“Population1”返回任何内容。这就是为什么您会得到0行的原因。 - Lamak
展示一些来自这两个表的样本数据和期望的输出,然后我们可以帮助您。 - user5886152
第二个查询显示了在Population2中没有相应记录的所有行在Population1中的情况。 - Anand
3个回答

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
谢谢!我应该认出这个。所以,为了验证我的理解,在第一个查询中将P1包含在FROM子句中,我没有引用父查询中的表的相同实例,因此不以任何方式连接到父查询。而在第二个查询中,在WHERE子句中使用P1,则使其成为相关子查询,并且确实引用了父查询的P1表。是这样吗? - Tyler

0

第一个例子实际上并不是指创建逻辑的基本表,这会导致不可预测的逻辑。

另一种实现相同逻辑的方法是:

SELECT payer_id
FROM Population1 P1
LEFT JOIN Population2 P2 ON
    P2.Payer_Id = P1.Payer_Id
WHERE
    P2.Payer_Id IS NULL

1
第一个查询的逻辑是可以预测的,但却没有实际用处。 - Hogan

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 --> 存在某些行 -> 不要返回此行

payer_id 2 --> 存在某些行 -> 不要返回此行


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接