为什么而当留在WHERE子句不等同于相同的左与条件加入ON加入? [重复](Why and wh

2019-08-18 06:21发布

这个问题已经在这里有一个答案:

  • SQL联接:关于第where子句对 17回答
  • “上..和”之间的区别和“..其中”在SQL左连接? 6个回答

我遇到一个非常混乱的局面,这让我怀疑我的理解在SQL Server连接。

SELECT t1.f2 
FROM   t1 
LEFT JOIN t2 
ON t1.f1 = t2.f1 AND cond2 AND t2.f3 > something 

不给相同的结果:

SELECT t1.f2 
FROM   t1 
LEFT JOIN t2 
ON t1.f1 = t2.f1 AND cond2 
WHERE  t2.f3 > something 

可如果这两个查询都应该是相等的或不告诉请人帮助吗?

谢谢

Answer 1:

on当子句用于join寻找匹配的行。 在where子句中使用的所有的连接完成后,过滤行。

与迪斯尼卡通总统投票的例子:

declare @candidates table (name varchar(50));
insert @candidates values 
    ('Obama'), 
    ('Romney');
declare @votes table (voter varchar(50), voted_for varchar(50));
insert @votes values 
    ('Mickey Mouse', 'Romney'),
    ('Donald Duck', 'Obama');

select  *
from    @candidates c
left join    
        @votes v
on      c.name = v.voted_for
        and v.voter = 'Donald Duck'

这仍然返回Romney即使Donald没有为他投票。 如果从移动状态onwhere子句:

select  *
from    @candidates c
left join    
        @votes v
on      c.name = v.voted_for
where   v.voter = 'Donald Duck'

Romney将不再在结果集中。



Answer 2:

两者都是从字面上不同。

第一查询表确实的滤波t2表的接合前发生。 所以结果将被加入上表t1产生的所有记录t1将被列入名单上显示。

从总的结果,第二个过滤器的接合表后完成。


下面是一个例子

表格1

ID   Name
1    Stack
2    Over 
3    Flow

表2

T1_ID   Score
1       10
2       20
3       30

在第一个查询,它看起来像这样,

SELECT  a.*, b.Score
FROM    Table1 a
        LEFT JOIN Table2 b
           ON a.ID = b.T1_ID AND
              b.Score >= 20

它的作用是连接表之前,的记录table2是由得分第一过滤。 因此,将表1上被连接的唯一记录

T1_ID   Score
2       20
3       30
  • SQLFiddle演示

因为ScoreT1_ID只有10分的查询的结果是

ID   Name    Score
1    Stack   NULL
2    Over    20
3    Flow    30
  • SQLFiddle演示

而第二个查询是不同的。

SELECT  a.*, b.Score
FROM    Table1 a
        LEFT JOIN Table2 b
           ON a.ID = b.T1_ID
WHERE   b.Score >= 20

它首先加入的记录是否有其他表或不匹配的记录。 因此,其结果将是

ID   Name    Score
1    Stack   10
2    Over    20
3    Flow    30
  • SQLFiddle演示

和过滤发生b.Score >= 20 。 所以最终的结果将是

ID   Name    Score
2    Over    20
3    Flow    30
  • SQLFiddle演示


Answer 3:

在第一种情况下,结果在t2被过滤为一体的连接部分。

在第二种情况下,有可能是从更多的行t2

从本质上讲,该组记录在两个查询加盟将是不一样的。



Answer 4:

它确实有差别,因为在第二种情况下你所申请的地方后,就在左连接



Answer 5:

CREATE TABLE Company
(
CompanyId TinyInt Identity Primary Key,
CompanyName Nvarchar(50) NULL
)
GO

INSERT Company VALUES('DELL')
INSERT Company VALUES('HP')
INSERT Company VALUES('IBM')
INSERT Company VALUES('Microsoft')
GO

CREATE TABLE Candidate
(
CandidateId tinyint identity primary key,
FullName nvarchar(50) NULL,
CompanyId tinyint REFERENCES Company(CompanyId)
)
GO

INSERT Candidate VALUES('Ron',1)
INSERT Candidate VALUES('Pete',2)
INSERT Candidate VALUES('Steve',3)
INSERT Candidate VALUES('Steve',NULL)
INSERT Candidate VALUES('Ravi',1)
INSERT Candidate VALUES('Raj',3)
INSERT Candidate VALUES('Kiran',NULL)
GO

SELECT * from Company c
SELECT * from Candidate c

-- A simple left outer Join
SELECT * FROM Company c LEFT OUTER JOIN Candidate c2
ON c.CompanyId = c2.CompanyId

--Left Outer Join ON and AND condition fetches 5 rows wtih NULL value from right side table 
SELECT * FROM Company c LEFT OUTER JOIN Candidate c2
ON c.CompanyId = c2.CompanyId
AND c.CompanyName = 'DELL' 

--Left Outer Join ON and where clause fetches only required rows
SELECT * FROM Company c LEFT OUTER JOIN Candidate c2
ON c.CompanyId = c2.CompanyId
AND c.CompanyName = 'DELL' 
WHERE c.CompanyName='IBM'


文章来源: Why and when a LEFT JOIN with condition in WHERE clause is not equivalent to the same LEFT JOIN in ON? [duplicate]