1

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

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

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

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

TIA

4

1 回答 1

1

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

MySQL 使用 GROUP BY 的扩展,它允许选择列表中的列出现在聚合函数或 GROUP BY 子句之外,但这可能会导致意外结果。(参见MySQL 对 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

或者您可以使用 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

于 2013-06-12T01:11:20.603 回答