2017-05-26 85 views
-1

我有時會與左連接和OR混淆。左外連接 - 有什麼區別?

這裏在下面的兩個代碼示例中,只有一個區別。一個樣本中的WHERE子句中有一個括號,而另一個樣本中沒有括號。

顯然,我得到了不同的結果。我想了解發生了什麼。

謝謝。

SELECT FROM TABLE_A as A 
LEFT OUTER JOIN TABLE_B as B 
     ON 
     A.col1 = B.col1 AND 
     A.col2 = B.col2 AND 
     A.col3 = B.col3 
     WHERE 
     B.col1 IS NULL OR B.col2 IS NULL OR B.col3 IS NULL AND 
     B.col4= 'R' AND 
     B.col5 != 'DR' 


SELECT FROM TABLE_A as A 
LEFT OUTER JOIN TABLE_B as B 
     ON 
     A.col1 = B.col1 AND 
     A.col2 = B.col2 AND 
     A.col3 = B.col3 
     WHERE 
     (B.col1 IS NULL OR B.col2 IS NULL OR B.col3 IS NULL) AND 
     B.col4= 'R' AND 
     B.col5 != 'DR' 
+0

這個問題是關於運算符優先級 - 它無關,與加入「左外」或以其他方式。 –

+0

也是,你不能在oracle中使用'as'作爲表別名。 –

回答

0
(B.col1 IS NULL OR B.col2 IS NULL OR B.col3 IS NULL) 

在第二種情況下,先在支架上的表達式進行求值,然後將下面的「:像這樣 - ,其中COL4 =「R」和COL5 =「DR」只從表-B加入的行AND「操作符被應用。 !所以結果,如果上述托架表達相與B.col4 =「R」,然後將其相與B.col5 =「DR」

B.col1 IS NULL OR B.col2 IS NULL OR B.col3 IS NULL AND 
    B.col4= 'R' AND 
    B.col5 != 'DR' 

在第一種情況下,將其評價像以下:

(B.col1 IS NULL) OR (B.col2 IS NULL) OR (B.col3 IS NULL AND B.col4= 'R' AND B.col5 != 'DR') 
1

AND操作符比OR更高的優先級,讓你的第一個WHERE子句可以寫成這樣:

WHERE 
    B.col1 IS NULL OR B.col2 IS NULL OR (B.col3 IS NULL AND 
    B.col4= 'R' AND 
    B.col5 != 'DR') 

但這可能不是您所希望的東西,如果你的WHERE的第二個版本條款是任何證據。如果你想檢查三列中的任何一列是NULL與其他兩個條件進行AND運算,那麼你應該使用括號。

+0

(B.col4 ='R'AND B.col5!='DR')是完全獨立的條件。 –

+0

據我所知,我已經解釋了兩個查詢之間的行爲差​​異。 –

+0

您是否編輯過您的早期回覆?只是問問。我沒有注意到最近的聲明。 –

1

我想你已經對左連接以及AND/OR運算符優先級感到困惑。

在您的第一個查詢中,順序從左到右應用,首先應用ANDS。

這意味着,你的第一個查詢是等價的:

SELECT * 
FROM table_a a 
     LEFT OUTER JOIN table_b b ON (a.col1 = b.col1 
            AND a.col2 = b.col2 
            AND a.col3 = b.col3) 
WHERE b.col1 IS NULL 
OR b.col2 IS NULL 
OR (b.col3 IS NULL 
     AND b.col4 = 'R' 
     AND b.col5 != 'DR'); 

但是,你的第二個查詢中的任何三個檢查空連接條件(這要麼是所有空,或所有不爲空,因爲您在連接條件中沒有滿足空值)以及檢查其餘兩列中是否存在值。這是沒有意義的 - 如果col1,col2和col3爲空,則意味着table_b行不是連接的一部分,所以col4和col5也將爲null。

相反,我認爲你的意思是使and b.col4 = 'R' and b.col5 != 'DR'左外連接條件的一部分 - 即。 !

WITH table_a AS (SELECT 1 col1, 1 col2, 1 col3 FROM dual UNION ALL 
       SELECT 2 col1, 2 col2, 2 col3 FROM dual UNION ALL 
       SELECT 3 col1, 3 col2, 3 col3 FROM dual), 
    table_b AS (SELECT 1 col1, 1 col2, 1 col3, 'R' col4, 'DP' col5 FROM dual UNION ALL 
       SELECT 2 col1, 2 col2, 2 col3, 'R' col4, 'DR' col5 FROM dual) 
SELECT * 
FROM table_a a 
     LEFT OUTER JOIN table_b b ON (a.col1 = b.col1 
            AND a.col2 = b.col2 
            AND a.col3 = b.col3 
            AND b.col4 = 'R' 
            AND b.col5 != 'DR'); 

     COL1  COL2  COL3  COL1  COL2  COL3 COL4 COL5 
---------- ---------- ---------- ---------- ---------- ---------- ---- ---- 
     1   1   1   1   1   1 R DP 
     2   2   2          
     3   3   3          
+0

感謝你和所有在這裏回覆的人。經過密切觀察,我明白了我錯在哪裏。 –

0

你的第二個查詢不是LEFT OUTER JOIN

SELECT * 
FROM TABLE_A A 
     LEFT OUTER JOIN TABLE_B B 
     ON ( A.col1 = B.col1 
      AND A.col2 = B.col2 
      AND A.col3 = B.col3) 
WHERE (B.col1 IS NULL OR B.col2 IS NULL OR B.col3 IS NULL) 
AND B.col4= 'R' 
AND B.col5 != 'DR' 

WHERE子句將只接受行,其中和B.col5NOT NULL,這隻會在表格連接時出現,這意味着連接條件實際上是INNER JOIN

但是,條件(B.col1 IS NULL OR B.col2 IS NULL OR B.col3 IS NULL)(A.col1 = B.col1 AND A.col2 = B.col2 AND A.col3 = B.col3)不能同時滿足,因爲NULL值不能等於任何其他值(包括另一個NULL)。所以查詢不應該返回任何行。

第一個查詢是:

SELECT * 
FROM TABLE_A A 
     LEFT OUTER JOIN TABLE_B B 
     ON ( A.col1 = B.col1 
      AND A.col2 = B.col2 
      AND A.col3 = B.col3) 
WHERE B.col1 IS NULL 
OR  B.col2 IS NULL 
OR  (B.col3 IS NULL AND B.col4= 'R' AND B.col5 != 'DR') 

這將返回行時B.col1 IS NULL OR B.col2 IS NULL(B.col3 IS NULL AND B.col4= 'R' AND B.col5 != 'DR')永遠不會匹配,因爲加盟條件將強制要麼B.col3NULL(當有在LEFT OUTER JOIN匹配)或者和B.col5都是NULL(當在LEFT OUTER JOIN中沒有匹配時)。

什麼,你實際上可能試圖實現(雖然它是從你的問題不清楚)是:

SELECT * 
FROM TABLE_A A 
     LEFT OUTER JOIN TABLE_B B 
     ON ( A.col1 = B.col1 
      AND A.col2 = B.col2 
      AND A.col3 = B.col3 
      AND   B.col4 = 'R' 
      AND   B.col5 != 'DR') 
相關問題