簡體   English   中英

LEFT JOIN返回與INNER JOIN相同的結果

[英]LEFT JOIN returns same result as INNER JOIN

我有一張桌子(磨砂),有1600個獨特的物品。 第二張表有100萬加。 我運行INNER JOIN並獲得65場比賽:

SELECT a.`BW Parent Number` , a.`Vendor Name`, b.`Parent Supplier Name` 
FROM `scrubs` AS a
JOIN pdwspend AS b ON a.`BW Parent Number` = b.`Child Supplier ID`
WHERE a.`year` =2014
AND b.`BU ID` = 'BU_1'
AND b.version LIKE '%GOV%'
GROUP BY a.`BW Parent Number` 

然后我運行LEFT OUTER JOIN並獲得相同的結果,結果為65:

SELECT a.`BW Parent Number` , a.`Vendor Name`, b.`Parent Supplier Name`  
FROM `scrubs` AS a
LEFT OUTER JOIN pdwspend AS b ON a.`BW Parent Number` = b.`Child Supplier ID` 
WHERE a.`year` =2014
AND b.`BU ID` = 'BU_1'
AND b.version LIKE '%GOV%'
GROUP BY a.`BW Parent Number`

為什么不從左表中引入所有行,並為b下不匹配的行顯示NULL。 Parent Supplier Name

謝謝!

因為您沒有使用on子句。 將其更改為:

SELECT a.`BW Parent Number`, a.`Vendor Name`, b.`Parent Supplier Name`
  FROM scrubs AS a
  LEFT OUTER JOIN pdwspend AS b
    ON a.`BW Parent Number` = b.`Child Supplier ID`
   and b.`BU ID` = 'BU_1'
   AND b.`version` LIKE '%GOV%'
 WHERE a.`year` = 2014

小組也沒有任何意義。 如果您正在聚合某些內容,則可以使用group by子句。

根據您對重復行的評論,這可能是因為您的名為“pdwspend”的表格對每個“兒童供應商ID”都有多行。 這是該表中唯一與您加入“磨砂”表的字段。 所以是的,對於pdwspend上的每個匹配行,你將擁有與第二個表一樣多的行(該表上可能有其他列,所以它們實際上不是“重復”行,你只是不選擇足夠的列用於說明)。

因為您只對選定數量的列感興趣,並且不希望基於這些列重復行,您可以嘗試使用以下方法進行區分:

(你在評論中輸入錯誤的原因是因為你的內聯視圖 - 你的from子句中的子查詢 - 沒有選擇'父供應商名'字段,所以是的,它不存在於那里內聯視圖,因為您沒有將其添加到該內聯視圖的選擇列表中。

     select a.`BW Parent Number`, a.`Vendor Name`, b.`Parent Supplier Name`
       from scrubs a
  left join ( select distinct `Child Supplier ID`, `Parent Supplier Name`
                         from pdwspend
                        where `BU ID` = 'BU_1'
                          and `version` LIKE '%GOV') b
         on a.`BW Parent Number` = b.`Child Supplier ID`
      where a.`year` = 2014

為什么不從左表中提取所有行並為不匹配的行顯示NULL?

你的LEFT JOIN沒有按預期工作的原因是因為WHERE子句中該表的條件; 這有時被稱為“ 隱式內連接 ”。

最好通過演示來解釋。 以下是2個簡單的表格

    | USER_ID | FIRST_NAME |  LAST_NAME |
    |---------|------------|------------|
    |     123 |       Fred | Flintstone |
    |     456 |     Barney |     Rubble |

    |    ID | USER_ID |       NOTE_BODY |
    |-------|---------|-----------------|
    | 98765 |     123 | Yabba Dabba Doo |

正如您所期望的那樣,INNER JOIN只生成一行,其中User_ID值在兩個表中都匹配。

SELECT * FROM users u INNER JOIN user_notes n ON u.User_ID = n.User_ID;

    | USER_ID | FIRST_NAME |  LAST_NAME |    ID |       NOTE_BODY |
    |---------|------------|------------|-------|-----------------|
    |     123 |       Fred | Flintstone | 98765 | Yabba Dabba Doo |

通過更改為LEFT JOIN,我們獲取用戶的所有記錄,但並非所有記錄都來自User_Notes,因此我們在這些列中獲得NULL

SELECT * FROM users u LEFT JOIN user_notes n ON u.User_ID = n.User_ID;

    | USER_ID | FIRST_NAME |  LAST_NAME |     ID |       NOTE_BODY |
    |---------|------------|------------|--------|-----------------|
    |     123 |       Fred | Flintstone |  98765 | Yabba Dabba Doo |
    |     456 |     Barney |     Rubble | (null) |          (null) |

但是,如果我們真的只想要連接表中的一些記錄會發生什么?

SELECT * FROM users u LEFT JOIN user_notes n ON u.User_ID = n.User_ID WHERE n.Note_Body ='Yabba Dabba Doo';

    | USER_ID | FIRST_NAME |  LAST_NAME |    ID |       NOTE_BODY |
    |---------|------------|------------|-------|-----------------|
    |     123 |       Fred | Flintstone | 98765 | Yabba Dabba Doo |

好吧,如果我們使用WHERE條件,效果與INNER JOIN相同,現在我們沒有獲得所有用戶記錄,這是一個隱式內連接

我們沒有獲得所有用戶記錄的原因是因為我們現在已經堅持要求所有結果行必須在可能為NULL的列中具有特定值。 因此,我們可以改變WHERE條件以允許NULL。

SELECT * FROM users u LEFT JOIN user_notes n ON u.User_ID = n.User_ID WHERE(n.Note_Body ='Yabba Dabba Doo'OR n.Note_Body IS NULL );

    | USER_ID | FIRST_NAME |  LAST_NAME |     ID |       NOTE_BODY |
    |---------|------------|------------|--------|-----------------|
    |     123 |       Fred | Flintstone |  98765 | Yabba Dabba Doo |
    |     456 |     Barney |     Rubble | (null) |          (null) |

要么

我們不是在連接表上使用WHERE子句,而是添加到連接條件(即ON之后)

SELECT * FROM users u LEFT JOIN user_notes n ON u.User_ID = n.User_ID AND n.Note_Body ='Yabba Dabba Doo';

    | USER_ID | FIRST_NAME |  LAST_NAME |     ID |       NOTE_BODY |
    |---------|------------|------------|--------|-----------------|
    |     123 |       Fred | Flintstone |  98765 | Yabba Dabba Doo |
    |     456 |     Barney |     Rubble | (null) |          (null) |

因此,在使用外連接時要小心,where子句不會覆蓋外連接允許的NULL。

請參閱上面的SQLFiddle演示

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM