복붙노트

[SQL] 절은 같은 왼쪽에 일치하지 않는 WHERE 왼쪽이에 조건 가입 할 때 ON에 왜와 가입? [복제]

SQL

절은 같은 왼쪽에 일치하지 않는 WHERE 왼쪽이에 조건 가입 할 때 ON에 왜와 가입? [복제]

나는 나의가 SQL 서버에 조인 내 모든 이해를 의심하게하는 매우 혼란 상황을 경험하고있다.

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 

이 두 개의 쿼리가 동등하다고 가정이나하지 않으면 이야기가 다른 사람의 도움을 기쁘게 할 수 있습니까?

고마워

해결법

  1. ==============================

    1.(가) 행 일치를 찾고 가입 할 때 절에 사용됩니다. WHERE 절은 모든 가입 완료 후 필터 행에 사용됩니다.

    (가) 행 일치를 찾고 가입 할 때 절에 사용됩니다. 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'
    

    도널드 그를 위해 투표하지 않은 경우에도이 여전히 롬니를 반환합니다. 당신은 where 절에에에서 상태를 이동하는 경우 :

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

    롬니는 더 이상 결과 집합에 없습니다.

  2. ==============================

    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
    

    그것이 무엇을하면 테이블을 조인하기 전에이며, 표 2의 기록은 점수에 의해 처음으로 필터링됩니다. 표에 합류 할 수있는 유일한 기록은 그래서

    T1_ID   Score
    2       20
    3       30
    

    T1_ID의 점수는 10이기 때문에 쿼리의 결과는

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

    두 번째 쿼리는 다르지만.

    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
    
  3. ==============================

    3.첫 번째 경우에는 T2의 결과 결합의 일부로서 필터링된다.

    첫 번째 경우에는 T2의 결과 결합의 일부로서 필터링된다.

    두 번째 경우, T2에서 사용할 수 많은 행이있을 수 있습니다.

    기본적으로, 레코드의 집합은 동일하지 않습니다 두 개의 쿼리에 합류했다.

  4. ==============================

    4.그것은 두 번째 경우에 당신이 왼쪽 않습니다 후에 어디에 가입 적용되기 때문에 변화를 않습니다

    그것은 두 번째 경우에 당신이 왼쪽 않습니다 후에 어디에 가입 적용되기 때문에 변화를 않습니다

  5. ==============================

    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'
    
  6. from https://stackoverflow.com/questions/15706112/why-and-when-a-left-join-with-condition-in-where-clause-is-not-equivalent-to-the by cc-by-sa and MIT license