2014-09-21 164 views
4

我有一个包含1600个唯一项目的表(磨砂)。第二张桌子有100万加。我跑我的INNER JOIN,并获得65场比赛:LEFT JOIN返回与INNER JOIN相同的结果

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

谢谢!

回答

9

因为您没有使用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子句中的子查询)没有选择'Parent Supplier Name'字段,所以是的,它不存在于内联视图中,因为你没有将它添加到select内联视图列表。

 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 
+0

会发生什么情况是,从表pdwspend每个b.'Child供应商ID'可能会出现数百次。当我没有它时,它会带来每一场比赛,所以我有很多重复的行。我认为一个更好的解决方案可能会在这一方面......这也给我一个错误!: – nangys 2014-09-21 05:18:20

+0

SELECT a.'BW Parent Number',a.'Vendor Name',b。'父供应商Name' FROM磨砂AS一 LEFT OUTER JOIN( SELECT DISTINCT'儿童供应商ID' FROM pdwspend WHERE'year' = 2014 和'BU ID' = 'BU_1' 和版本LIKE“% GOV%')AS b ON a.'BW Parent Number' = b.'Child Supplier ID' WHERE a.'year' = 2014#1054 - '字段列表'中的未知列'b.Parent Supplier Name' – nangys 2014-09-21 05:20:13

+0

您在'select distinct subquery'内不包含'b.Parent Supplier Name'。重新看Brian的查询并复制它 – 2014-09-21 23:24:06

7

为什么不左表中把所有的行,并表示日NULL那些不匹配的?

您的LEFT JOIN未按预期工作的原因是由于WHERE条款中该表的条件;这有时被称为“隐式内部连接”。

这是最好的解释说明。下面是两个简单的表

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

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

所以如你所料,内连接只产生一个行,其中USER_ID值两个表中的匹配。

SELECT * FROM用户üINNER JOIN user_notes N于u.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ü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用户üLEFT JOIN user_notes N于u.User_ID = n.User_ID WHERE n.Note_Body = 'YABBA Dabba斗';

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

那么,如果我们使用WHERE条件,效果是作为INNER JOIN一样,现在我们没有得到所有用户的记录,这是一个隐含的内部联接

我们没有得到所有用户记录的原因是因为我们现在坚持所有结果行必须在可能为NULL的列中具有特定值。所以,我们可以改变WHERE条件来允许NULL。

SELECT * FROM用户üLEFT JOIN user_notes N于u.User_ID = n.User_ID WHERE(n.Note_Body = 'YABBA Dabba斗' 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) | 

OR

而不是使用上,我们增加了加盟条件(ieafter ON)

SELECT * FROM用户üLEFT JOIN连接表的WHERE子句user_notes n ON u.User_ID = n.User_ID AND n.Note_Body ='Yabba Dabba斗“;

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

所以,要小心使用外连接,你的where子句不会覆盖外连接允许空值。

See the above as a SQLFiddle demonstration

+0

感谢您的回复!这是非常有用的 – nangys 2014-09-22 00:48:56

+0

没问题,upvote也表示赞赏(提示) – 2014-09-22 00:49:29

+0

@robsch很好的编辑,谢谢。 – 2016-01-19 10:50:35