ON 절의 위치는 실제로 무엇을 의미합니까?


23

일반적인 JOIN ... ON ...구문은 잘 알려져 있습니다. 그러나 ON절을 해당 절과 별도로 배치 할 수도 있습니다 JOIN. 이것은 실제로는 거의 보이지 않으며 튜토리얼에서는 볼 없으며 이것이 가능하다는 언급조차 하는 웹 리소스를 찾지 못했습니다 .

다음은 함께 사용할 스크립트입니다.

SELECT *
INTO #widgets1
FROM (VALUES (1), (2), (3)) x(WidgetID)


SELECT *
INTO #widgets2
FROM (VALUES (1, 'SomeValue1'), (2, 'SomeValue2'), (3, 'SomeValue3')) x(WidgetID, SomeValue)

SELECT *
INTO #widgetProperties
FROM (VALUES
    (1, 'a'), (1, 'b'),
    (2, 'a'), (2, 'b'))
x(WidgetID, PropertyName)


--q1
SELECT w1.WidgetID, w2.SomeValue, wp.PropertyName
FROM #widgets1 w1
LEFT JOIN #widgets2 w2 ON w2.WidgetID = w1.WidgetID
LEFT JOIN #widgetProperties wp ON w2.WidgetID = wp.WidgetID AND wp.PropertyName = 'b'
ORDER BY w1.WidgetID


--q2
SELECT w1.WidgetID, w2.SomeValue, wp.PropertyName
FROM #widgets1 w1
LEFT JOIN #widgets2 w2 --no ON clause here
JOIN #widgetProperties wp
 ON w2.WidgetID = wp.WidgetID AND wp.PropertyName = 'b'
 ON w2.WidgetID = w1.WidgetID
ORDER BY w1.WidgetID


--q3
SELECT w1.WidgetID, w2.SomeValue, wp.PropertyName
FROM #widgets1 w1
LEFT JOIN (
    #widgets2 w2 --no SELECT or FROM here
    JOIN #widgetProperties wp
    ON w2.WidgetID = wp.WidgetID AND wp.PropertyName = 'b')
ON w2.WidgetID = w1.WidgetID
ORDER BY w1.WidgetID

q1은 정상적으로 보입니다. q2와 q3에는이 ON절의 특이한 위치가 있습니다.

이 스크립트는 반드시 의미가 없습니다. 의미있는 시나리오를 고안하기가 어려웠습니다.

이 특이한 구문 패턴은 무엇을 의미합니까? 이것이 어떻게 정의됩니까? 나는 두 ON조항에 대한 모든 입장과 순서 가 허용되는 것이 아님을 알았다 . 이것을 지배하는 규칙은 무엇입니까?

또한 이런 쿼리를 작성하는 것이 좋은 생각입니까?

답변:


32

당신이 보면 FROM절 구문 다이어그램 당신은 단 하나의 장소가 있다는 것을 볼 수 있습니다 ON절 :

<joined_table> ::= 
{
    <table_source> <join_type> <table_source> ON <search_condition> 
    ...
}

당신이 혼란을 찾으십시오, 간단한 재귀 때문에 <table_source><joined_table> 위의 또 다른 될 수 있습니다 <joined_table>

[ FROM { <table_source> } [ ,...n ] ] 
<table_source> ::= 
{
    table_or_view_name ... 
    ...
    | <joined_table> 
    ...
}

혼동을 피하기 위해 (예와 같이) 분명하지 않은 경우 괄호를 사용하여 시각적으로 분리해야합니다 <table_sources>. 쿼리 파서는 필요하지 않지만 사람에게는 유용합니다.


33

조인에 관련된 논리 테이블을 결정합니다.

간단한 예를 들어

SELECT w1.WidgetID,
       w2.SomeValue,
       wp.PropertyName
FROM   #widgets1 w1
       LEFT JOIN #widgets2 w2
         ON w2.WidgetID = w1.WidgetID
       JOIN #widgetProperties wp
         ON w2.WidgetID = wp.WidgetID
            AND wp.PropertyName = 'b'
ORDER  BY w1.WidgetID 

#widgets1은 외부 조인 상태로 유지됩니다 #widgets2. 결과는 내부 조인 된 가상 테이블을 형성합니다 #widgetProperties. 술어 w2.WidgetID = wp.WidgetID는 초기 외부 조인의 널 확장 행이 필터링되어 모든 조인 내부 조인을 효과적으로 작성 함을 의미합니다.

이것은 q2와 다릅니다 ...

SELECT w1.WidgetID,
       w2.SomeValue,
       wp.PropertyName
FROM   #widgets1 w1
       LEFT JOIN #widgets2 w2 --no ON clause here
                 JOIN #widgetProperties wp
                   ON w2.WidgetID = wp.WidgetID
                      AND wp.PropertyName = 'b'
         ON w2.WidgetID = w1.WidgetID
ORDER  BY w1.WidgetID

#widgets2내부가에 결합되었습니다 #widgetProperties. 해당 조인으로 인한 가상 테이블은 왼쪽 외부 조인의 오른쪽 테이블입니다.#widgets1

파생 테이블 또는 공통 테이블 표현식을 사용하여 동일한 결과를 얻을 수 있습니다.

WITH VT2
     AS (SELECT w2.WidgetID,
                w2.SomeValue,
                wp.PropertyName
         FROM   #widgets2 w2 
                JOIN #widgetProperties wp
                  ON w2.WidgetID = wp.WidgetID
                     AND wp.PropertyName = 'b')
SELECT w1.WidgetID,
       VT2.SomeValue,
       VT2.PropertyName
FROM   #widgets1 w1
       LEFT JOIN VT2
         ON VT2.WidgetID = w1.WidgetID
ORDER  BY w1.WidgetID 

... 또는 가상 테이블을 재정렬하고 RIGHT JOIN대신 사용할 수 있습니다 .

SELECT w1.WidgetID,
       w2.SomeValue,
       wp.PropertyName
FROM   #widgets2 w2
       INNER JOIN #widgetProperties wp
               ON w2.WidgetID = wp.WidgetID
                  AND wp.PropertyName = 'b'
       RIGHT JOIN #widgets1 w1
               ON w2.WidgetID = w1.WidgetID
ORDER  BY w1.WidgetID 

이다 여기 Itzik 벤 웨이 코 뮤니시 적용

... JOIN 조건은 테이블 순서와의 관계를 따라야합니다. 즉, 순서대로 테이블 T1, T2, T3 및 T4를 지정하고 JOIN 조건이 T1과 T2, T2와 T3와 T3와 T4와 일치하면 테이블 순서와 반대 순서로 JOIN 조건을 지정해야합니다. , 이렇게 :

FROM   T1
       <join_type> T2 T2
                  <join_type> T3 T3
                             <join_type> T4
                               ON T4.key = T3.key
                    ON T3.key = T2.key
         ON T2.key = T1.key 

이 조인 기술을 다른 방식으로 살펴 보려면 주어진 JOIN 조건이 바로 위에있는 테이블 이름 또는 이전 JOIN 조건이 이미 참조하고 해결 한 테이블 이름 만 참조 할 수 있습니다.

그러나 기사에는 많은 부정확성이 있습니다. Lubor Kollar후속 편지도 참조하십시오 .


감사합니다 Martin,이 답변은 매우 도움이됩니다. 공식 문법에 대한 그의 요점이 문제를 완전히 이해하는 데 도움이 되었기 때문에 다른 것을 받아들입니다. 특히 "치안 적 관계"는 잘못된 생각 인 것 같습니다. 목록과 역순 목록이 아닌 트리입니다. mustaccio는 Itziks의 해석이 왜 옳지 않은지를 이해하기위한 틀을 제공했습니다.
boot4life
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.