左连接返回超过预期

时间:2011-10-10 10:20:51

标签: mysql sql

使用以下查询

select *
from table1
left join table2 on table1.name = table2.name

table1返回16行,table2返回35行。

由于left join,我期望上面的查询返回16行,但它返回35行。 right join也会返回35行

为什么会发生这种情况,如何让它返回16行?

6 个答案:

答案 0 :(得分:12)

如果表1中的行的外键被table2中的多行引用,则LEFT JOIN可以从table1返回多个数据副本。

如果您希望它只返回16行,每个表1行一个,并且表2的随机数据集,则只能使用普通的GROUP BY:

select *
from table1
left join table2 on table1.name = table2.name
group by table1.name

GROUP BY根据字段聚合行,因此这会将所有table1重复项折叠为一行。通常,您指定聚合函数来解释行应如何折叠(例如,对于数字行,您可以使用SUM()折叠它,因此一行将是总数)。如果您只想要一个随机行,请不要指定任何聚合函数。 MySQL默认只选择一行(请注意,这是特定于MySQL的,大多数数据库都要求您在分组时指定聚合)。它选择它的方式在技术上并不是“随机的”,但它不一定是你可预测的。我想通过“随机”你真的只是意味着“任何行都会做”。

答案 1 :(得分:4)

假设您有以下表格:

tbl1:
|Name |
-------
|Name1|
|Name2|

tbl2:
|Name |Value |
--------------
|Name1|Value1|
|Name1|Value2|
|Name3|Value1|

对于你的LEFT JOIN,你会得到:

|tbl1.Name|tbl2.Name|Value |
----------------------------
|Name1    | Name1   |Value1|
|Name1    | Name1   |Value2|
|Name2    | NULL    | NULL |

因此,LEFT JOIN意味着将返回LEFT(第一个)表中的所有记录,无论它们是否存在于右表中。

对于您的问题,您需要指定一些特定字段,而不是使用“*”并添加GROUP BY tbl1.Name - 因此您的查询将如下所示

select tbl1.Name, SOME_AGGREGATE_FUNCTION(tbl2.specific_field), ...
from table1
left join table2 on table1.name = table2.name
GROUP BY tbl1.Name

答案 2 :(得分:1)

使用它的一种方法是使用SQL distinct的强大功能。

select distinct tbl1.id, *
from table1 tbl1
left join table2 tbl2 on tbl2.name = tbl1.name

where
 ....................

请注意,我也在使用别名。

答案 3 :(得分:0)

如果表格中的名称列不是唯一的,那么您可能只是在table2上有重复项。

尝试跑步:

select * from table2 where name not in (select name from table1);

如果没有得到任何结果,那么名称列上的重复数据就是额外行返回的原因。

答案 4 :(得分:0)

答案 5 :(得分:-1)

根据您的评论“table2中的随机行,只要table1中的名称与table2中的名称匹配”,您可以使用以下内容:

select table1.name, (select top 1 somecolumn from table2 where table2.name = table1.name)
from table1

请注意,top 1不是mysql,而是SQL Server