Query

在混合新舊連接語法時查詢邏輯處理階段

  • March 10, 2012

FROM如果我混合使用新舊語法來連接表,誰能澄清為什麼表的順序很重要?例如,

SELECT * 
FROM table1 a, table2 b
INNER JOIN table3 c ON (c.a_id = a.id) -- error - a.id - invalid identifier
WHERE (a.id = b.a_id)

SELECT * 
FROM table2 b, table1 a 
INNER JOIN table3 c ON (c.a_id = a.id) -- ok, table1 a is the last in FROM
WHERE (a.id = b.a_id)

我不會使用這種醜陋的查詢,但我相信在查詢中指定的所有表都FROM應該對查詢的其他部分可見。

我不認為這取決於 RDMS,因為 SQLServer、Oracle 和 Mysql 的行為方式相同 - 第一次查詢出錯,第二次沒有錯誤。我肯定遺漏了一些明顯的東西,但我沒有找到任何描述它為什麼會這樣工作的東西。

謝謝你。

這與逗號運算符的優先級有關。如MySQL 文件中所述

逗號運算符的優先級小於INNER JOIN, CROSS JOIN, LEFT JOIN, 等等。如果在存在連接條件時將逗號連接與其他連接類型混合使用,則會出現表單錯誤Unknown column 'col_name' in 'on clause' may occur

您通過下面的重寫得到相同的結果(其中ON子句的位置清楚地表明了連接操作的邏輯順序)

失敗

SELECT * 
FROM   table1 a 
      INNER JOIN (table2 b 
                  INNER JOIN table3 c 
                    ON c.a_id = a.id ) -- error - a.id - invalid identifier 
        ON a.id = b.a_id 

成功

SELECT * 
FROM   table2 b 
      INNER JOIN (table1 a 
                  INNER JOIN table3 c 
                    ON c.a_id = a.id ) 
        ON a.id = b.a_id 

在成功的那個a首先加入到cc.a_id = a.id然後由該加入產生的虛擬表加入到所有工作正常的虛擬表b上。a.id = b.a_id

對於第b一次嘗試連接失敗的c那個c.a_id = a.id,因為引用 table 是無效的a。該ON子句只能引用它之前的表或前一個ON子句已經引入的表。

根據條件c.a_id = a.ida.id = b.a_id然後c.a_id=b.a_id您可以將連接條件更改為該條件,它會起作用,或者您當然也可以使用派生表或視圖來更改優先級並確保a,b在加入之前被視為邏輯連接單元c

SELECT * 
FROM   (SELECT * 
       FROM   table2 b, 
              table1 a) ba 
      INNER JOIN table3 c 
        ON ( c.a_id = ba.id ) 
WHERE  ( ba.id = ba.a_id ) 

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