Sql-Server
SQL ANSI JOIN 優先級
我有一個看起來像這樣的查詢:
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