连接查询之间的语义差异

时间:2010-09-09 14:37:08

标签: sql sql-server sql-server-2008 left-join

我有两个问题,我认为这意味着同样的事情,但我不断得到不同的结果,我希望有人可以解释这些是如何不同的:

1

select * 
from table1 a 
left join table2 b on a.Id = b.Id and a.val = 0
where b.Id is null

2

select * 
from table1 a 
left join table2 b on a.Id = b.Id 
where b.Id is null 
    and a.val = 0

查询的目的是查找table1中的行和val = 0中不在table2中的行。

我也在使用sql server 2008,但我怀疑这是否重要。

3 个答案:

答案 0 :(得分:9)

当考虑左连接时,认为它们有3个概念阶段。

  1. 应用了联接过滤器
  2. 左侧行添加回
  3. 应用了where子句。
  4. 然后,您将看到为什么会得到不同的结果。

    这也解释了为什么这会返回结果

    select o.* 
    from sys.objects o
    left join sys.objects o2 on o.object_id=o2.object_id and 1=0
    

    而事实并非如此。

    select o.* 
    from sys.objects o
    left join sys.objects o2 on o.object_id=o2.object_id 
    where 1=0
    

答案 1 :(得分:1)

  SELECT * from TABLE1 t1
  WHERE Val = 0
  AND NOT EXISTS(SELEct 1 from Table2 t2 Where t1.Id = t2.Id)

答案 2 :(得分:1)

如果完全删除WHERE子句,使用LEFT OUTER JOIN表示左侧表格中的所有行都会出现,即使它们不满足{{1}标准。例如,没有行满足表达式JOIN但是这样:

1 = 0

仍然会导致table1中的所有行都返回SELECT * FROM table1 AS a LEFT OUTER JOIN table2 AS b ON a.Id = b.Id AND 1 = 0; 值匹配的位置。简而言之,这就是id的工作方式。

OUTER JOIN之后应用WHERE子句,因此

JOIN

将不返回任何行。