Sql-Server

SQL ANSI JOIN 優先級

  • November 3, 2012

我有一個看起來像這樣的查詢:

   SELECT *
     FROM TBLA A
LEFT JOIN TBLB B ON A.Col1 = B.Col2
RIGHT JOIN TBLC C ON B.Col3 = C.Col4
     JOIN TBLD D ON C.Col5 = D.Col6

連接將按什麼順序解決?我對 SQL Server 最感興趣,並將對它的解釋標記為答案,但對 ANSI/ISO 標準及其在各種 RDBMS 中的工作方式同樣感興趣。

這個問題的原因是要弄清楚為什麼結果與這個查詢不同

   SELECT *
     FROM TBLA A
CROSS JOIN TBLC C
LEFT JOIN TBLB B ON A.Col1 = B.Col2 AND B.Col3 = C.Col4
     JOIN TBLD D ON C.Col5 = D.Col6

從邏輯上講ON,連接是按照從左到右的子句順序解決的。

每個連接的輸出是一個進入下一個連接的虛擬表。

因此,對於您的問題中的查詢,虛擬表結果A LJ B將正確連接到C. 的連接條件B.Col3 = C.Col4將失去由原始左連接保留的任何空擴展行,有效地將第一個連接轉換回內連接,然後將生成的虛擬表(保留來自 的所有行C)內連接到D

所以你的初始查詢可以簡化為

SELECT *
FROM TBLA A
INNER JOIN TBLB B ON A.Col1 = B.Col2
RIGHT JOIN TBLC C ON B.Col3 = C.Col4
     JOIN TBLD D ON C.Col5 = D.Col6

這實際上與(A IJ B) ROJ (C IJ D)

子句的順序ON不一定與表在查詢中出現的順序相同。這也可以重寫為(C IJ D) LOJ (A IJ B)

SELECT *
FROM   TBLC C
      INNER JOIN TBLD D
        ON C.Col5 = D.Col6
      LEFT JOIN TBLA A
                INNER JOIN TBLB B
                  ON A.Col1 = B.Col2
        ON B.Col3 = C.Col4 

on 子句的位置意味著外連接是在兩個虛擬表之間執行的,而這兩個虛擬表是由單個表產生的 (C IJ D)(A IJ B)而不僅僅是在單個表上。

從概念上講,在您的第二個查詢中,虛擬表A x C與 B 保持連接,保留整個笛卡爾積,然後將其結果D與 predicate連接C.Col5 = D.Col6。這消除了最終結果中沒有內部連接的任何行,這C意味著D它相當於

SELECT *
FROM   TBLC C
      JOIN TBLD D
        ON C.Col5 = D.Col6
      CROSS JOIN TBLA A
      LEFT JOIN TBLB B
        ON A.Col1 = B.Col2
           AND B.Col3 = C.Col4 

引用自:https://dba.stackexchange.com/questions/28113