27

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 

この2つのクエリが同等であるかどうかを教えてください。

どうも

4

5 に答える 5

39

この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にもかかわらず、これはまだ戻ってきます。条件を the句からto句Donaldに移動すると、次のようになります。onwhere

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

Romney結果セットに含まれなくなります。

于 2013-03-29T15:29:53.307 に答える
22

どちらも文字通り違います。

t2最初のクエリは、テーブルの結合が行われる前にテーブルのフィルタリングを行います。したがって、結果はテーブルで結合され、t1すべてのレコードがt1リストに表示されます。

2 つ目は、テーブルの結合が完了した後の合計結果からフィルター処理されます。


これが例です

表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最初にスコアによってフィルター処理されることです。したがって、table1 で結合される唯一のレコードは

T1_ID   Score
2       20
3       30

Scoreのは 10 しかないためT1_IDです。クエリの結果は

ID   Name    Score
1    Stack   NULL
2    Over    20
3    Flow    30

2番目のクエリは異なりますが。

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

そしてフィルタリングが行われb.Score >= 20ます。したがって、最終結果は次のようになります

ID   Name    Score
2    Over    20
3    Flow    30
于 2013-03-29T15:24:16.610 に答える
1
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'
于 2013-03-29T15:41:47.840 に答える
0

最初のケースでは、結果t2は結合の一部としてフィルタリングされます。

2 番目のケースでは、より多くの行が から利用できる可能性がありますt2

基本的に、2 つのクエリで結合されたレコードのセットは同じではありません。

于 2013-03-29T15:21:19.643 に答える
0

2番目のケースでは、左結合を実行した後に適用するため、違いがあります

于 2013-03-29T15:22:00.017 に答える