试图计算从MySQL连接表返回的行数

时间:2013-06-12 00:54:58

标签: mysql join count

我正在尝试计算MySQL连接表返回的行数,即:

select *, count(pets.id) as pets_per_owner 
from owners 
left join pets 
   on owners.id=pets.owner_id

问题是所有连接的行都被分组。

有没有办法获取这些小计,但是显示所有返回(未分组)的行而没有单独的查询?

TIA

1 个答案:

答案 0 :(得分:1)

问题是您使用的聚合函数没有GROUP BY,因此结果会缩减为一行。

MySQL使用GROUP BY的扩展,它允许选择列表中的列出现在聚合函数或GROUP BY子句之外,但这会导致意外的结果。 (见MySQL Extensions to GROUP BY

来自MySQL文档:

  

MySQL扩展了GROUP BY的使用,因此选择列表可以引用GROUP BY子句中未命名的非聚合列。 ...您可以通过避免不必要的列排序和分组来使用此功能来获得更好的性能。但是,当GROUP BY中未命名的每个非聚合列中的所有值对于每个组都相同时,这非常有用。服务器可以自由选择每个组中的任何值,因此除非它们相同,否则所选的值是不确定的。此外,添加ORDER BY子句不会影响每个组中值的选择。选择值后会对结果集进行排序,而ORDER BY不会影响服务器选择的值。

为了解决这个问题,您应该做两件事,首先将select *替换为您需要返回的列的实际名称。其次,在您选择列表中包含的未聚合的列上使用GROUP BY。例如:

select owners.name, count(pets.id) as pets_per_owner 
from owners 
left join pets 
   on owners.id=pets.owner_id
group by owners.name

由于您在评论中发布了代码,因此很难准确确定您要查找的内容,但如果您想要宠物名称以及总计数,则可以使用以下方法之一:

select o.name,
  p.name pet_name,
  p2.pets_per_owner
from owners o
left join pets p
  on o.id = p.owner_id
left join 
(
  select owner_id, count(*) pets_per_owner
  from pets
  group by owner_id
) p2
  on o.id = p2.owner_id
  and p.owner_id = p2.owner_id;

请参阅SQL Fiddle with Demo

或者你可以使用GROUP_CONCAT函数在一行中列出宠物名称:

select owners.name, 
  group_concat(pets.name separator ', ') pet_name,
  count(pets.id) as pets_per_owner 
from owners 
left join pets 
   on owners.id=pets.owner_id
group by owners.name;

请参阅SQL Fiddle with Demo