2011-01-24 91 views
13

我很好奇爲什麼我們需要使用LEFT JOIN,因爲我們可以使用逗號來選擇多個表。左加入或使用逗號(,)從多個表中選擇

LEFT JOIN和使用逗號來選擇多個表之間有什麼區別。

哪一個更快?

這裏是我的代碼:

SELECT mw.*, 
      nvs.* 
    FROM mst_words mw 
LEFT JOIN (SELECT no as nonvs, 
        owner, 
        owner_no, 
        vocab_no, 
        correct 
      FROM vocab_stats 
      WHERE owner = 1111) AS nvs ON mw.no = nvs.vocab_no 
    WHERE (nvs.correct > 0) 
     AND mw.level = 1 

...和:

SELECT * 
    FROM vocab_stats vs, 
     mst_words mw 
WHERE mw.no = vs.vocab_no 
    AND vs.correct > 0 
    AND mw.level = 1 
    AND vs.owner = 1111 
+1

第一個是OUTER(本例中爲LEFT)JOIN示例(ANSI-92),後者是INNER JOIN(ANSI-89,不支持OUTER連接)。除非總是有記錄來鏈接這兩個表格,否則他們不可能返回相同的結果。 –

+0

@OMG後者不是'INNER JOIN。由於它是笛卡兒乘積,因此它更接近CROSS JOIN定義。 – RichardTheKiwi

+1

ANSI-89語法...解釋計劃與使用'... FROM VOCAB_STATS s JOIN MSTWORDS w ON w.no = v.vocab_no ...'相同。再次 - **否,第二個查詢不返回笛卡爾積**。 –

回答

3

首先,是完全等效的,第一個查詢應該已被寫入

SELECT mw.*, 
      nvs.* 
    FROM mst_words mw 
LEFT JOIN (SELECT * 
      FROM vocab_stats 
      WHERE owner = 1111) AS nvs ON mw.no = nvs.vocab_no 
    WHERE (nvs.correct > 0) 
     AND mw.level = 1 

這樣兆瓦*和NVS *一起產生相同的一組作爲第二個查詢的單數*。你寫的查詢可以使用INNER JOIN,因爲它在nvs.correct上包含一個過濾器。

一般形式

TABLEA LEFT JOIN TABLEB ON <CONDITION> 

attempts找到基於條件表B的記錄。如果失敗,則保留TABLEA的結果,並將TableB中的所有列設置爲NULL。相比之下

TABLEA INNER JOIN TABLEB ON <CONDITION> 

attempts找到基於條件表B的記錄。 但是,如果失敗,TableA中的特定記錄將從輸出結果集中刪除。

CROSS JOIN的ANSI標準在兩個表之間產生一個Cartesian product

TABLEA CROSS JOIN TABLEB 
    -- # or in older syntax, simply using commas 
TABLEA, TABLEB 

語法的意圖是TABLEA中的EACH行被連接到TABLEB中的EACH行。因此A中的4行和B中的3行產生了12行輸出。當與WHERE子句中的條件配對時,它有時產生與INNER JOIN相同的行爲,因爲它們表達相同的事物(A和B之間的條件=>保留或不)。但是,在閱讀使用INNER JOIN而不是逗號的意圖時,它會更清晰。

從性能上看,大多數DBMS將比INNER JOIN更快地處理LEFT連接。逗號表示法可能會導致數據庫系統錯誤地解釋意圖併產生錯誤的查詢計劃 - 這是SQL92表示法的另一個優點。

爲什麼我們需要LEFT JOIN?如果上面的LEFT JOIN的解釋仍然不夠(保留A中的記錄而B中沒有匹配),則認爲要達到相同的效果,您需要在兩組之間使用舊的逗號符號實現相同的複雜UNION影響。 但如前所述,這不適用於您的示例,這實際上是隱藏在LEFT JOIN後面的INNER JOIN。

注:

  • 的RIGHT JOIN相同LEFT,不同之處在於它與TABLEB(右側)開始代替A.
  • 右和左JOINS都是外部聯接。字OUTER是可選的,即它可以被寫爲LEFT OUTER JOIN
  • 第三種OUTER連接是FULL OUTER連接,但這裏不討論。
0

分離的JOIN從WHERE可以很容易地閱讀,作爲連接邏輯不能與WHERE條件混淆。它通常也會更快,因爲服務器不需要進行兩個單獨的查詢並結合結果。

你給出的兩個例子並不是真的等價,因爲你在第一個例子中包含了一個子查詢。這是一個更好的例子:。

SELECT vs.*, mw.* 
FROM vocab_stats vs, mst_words mw 
LEFT JOIN vocab_stats vs ON mw.no = vs.vocab_no 
WHERE vs.correct > 0 
AND mw.level = 1 
AND vs.owner = 1111 
+0

SQL無效 – RichardTheKiwi

+0

謝謝,我剛剛刪除了這個錯字。 – Bazmatiq