简体   繁体   English

LEFT JOIN返回与INNER JOIN相同的结果

[英]LEFT JOIN returns same result as INNER JOIN

I have one table (scrubs) with 1600 unique items. 我有一张桌子(磨砂),有1600个独特的物品。 A second table with 1 million plus. 第二张表有100万加。 I run my INNER JOIN and get 65 matches: 我运行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` 

Then I run a LEFT OUTER JOIN and I get the same, 65 results: 然后我运行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`

Why is not bringing all the rows from the left table and showing NULL for the ones that don't match under b. 为什么不从左表中引入所有行,并为b下不匹配的行显示NULL。 Parent Supplier Name ? Parent Supplier Name

Thanks! 谢谢!

Because you are not using the on clause. 因为您没有使用on子句。 Change it to: 将其更改为:

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

Also the group by doesn't make any sense. 小组也没有任何意义。 You would use the group by clause if you're aggregating on something. 如果您正在聚合某些内容,则可以使用group by子句。

Based on your comment regarding repeated rows, that is probably because you table called "pdwspend" has more than one row for each 'Child Supplier ID'. 根据您对重复行的评论,这可能是因为您的名为“pdwspend”的表格对每个“儿童供应商ID”都有多行。 And that is the only field on that table with which you are joining the "scrubs" table. 这是该表中唯一与您加入“磨砂”表的字段。 So yes, for every matching row on pdwspend, you'll have as many rows as there are on that second table (there are likely other columns on that table, so they really are not "repeated" rows, you're just not selecting enough columns for that to be illustrated). 所以是的,对于pdwspend上的每个匹配行,你将拥有与第二个表一样多的行(该表上可能有其他列,所以它们实际上不是“重复”行,你只是不选择足够的列用于说明)。

Because you are only interested in a select number of columns and don't want rows 'repeated' based on those columns you can try distinct using: 因为您只对选定数量的列感兴趣,并且不希望基于这些列重复行,您可以尝试使用以下方法进行区分:

(the reason you get an error in the query you put in your comments is because your inline view -- the subquery in your from clause -- does not select the 'Parent Supplier Name' field, so yes, it does not exist in that inline view because you didn't add it to the select list of that inline view. (你在评论中输入错误的原因是因为你的内联视图 - 你的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

Why is it not bringing all the rows from the left table and showing NULL for the ones that don't match? 为什么不从左表中提取所有行并为不匹配的行显示NULL?

The reason your LEFT JOIN didn't work as expected is because of the conditions on that table in the WHERE clause; 你的LEFT JOIN没有按预期工作的原因是因为WHERE子句中该表的条件; this is sometimes called " implicit inner join " . 这有时被称为“ 隐式内连接 ”。

This is best explained by demonstration. 最好通过演示来解释。 Below are 2 simple tables 以下是2个简单的表格

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

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

So as you would expect, an INNER JOIN produces just one row where the User_ID values match in both tables. 正如您所期望的那样,INNER JOIN只生成一行,其中User_ID值在两个表中都匹配。

SELECT * FROM users u INNER JOIN user_notes n ON u.User_ID = n.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 |

And by changing to LEFT JOIN we get all records in Users but not all have information from User_Notes, so we get NULLs in those columns 通过更改为LEFT JOIN,我们获取用户的所有记录,但并非所有记录都来自User_Notes,因此我们在这些列中获得NULL

SELECT * FROM users u LEFT JOIN user_notes n ON u.User_ID = n.User_ID; 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) |

But what happens if we realy only want SOME records from the joined table? 但是,如果我们真的只想要连接表中的一些记录会发生什么?

SELECT * FROM users u LEFT JOIN user_notes n ON u.User_ID = n.User_ID WHERE n.Note_Body = 'Yabba Dabba Doo'; 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 |

Well if we use a WHERE condition, the effect is the same as an INNER JOIN, now we don't get all User records and this is an implicit inner join . 好吧,如果我们使用WHERE条件,效果与INNER JOIN相同,现在我们没有获得所有用户记录,这是一个隐式内连接

The reason we don't get all user records is because we have now insisted that all result rows MUST have a certain value in a column that might be NULL. 我们没有获得所有用户记录的原因是因为我们现在已经坚持要求所有结果行必须在可能为NULL的列中具有特定值。 So, we could alter the WHERE condition to permit NULLs. 因此,我们可以改变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 ); 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) |

OR 要么

Instead of using the WHERE clause on the joined table we add to the join conditions (ieafter ON ) 我们不是在连接表上使用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'; 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) |

So, be careful when using outer joins that your where clause does not override the NULLs that an outer join allows. 因此,在使用外连接时要小心,where子句不会覆盖外连接允许的NULL。

See the above as a SQLFiddle demonstration 请参阅上面的SQLFiddle演示

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM