Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/67.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mysql 按组左联接、求和和计数_Mysql_Sql - Fatal编程技术网

Mysql 按组左联接、求和和计数

Mysql 按组左联接、求和和计数,mysql,sql,Mysql,Sql,我有三张桌子:货物、商店和图片。在第一个表中存储商品名称。在第二个-不同库存商品的平衡,在第三个-商品图片链接。因此,商品与商店和图片有一对多的联系。 现在,我需要通过一次查询获得一个包含库存余额和图片计数的商品列表。 我是这样做的: SELECT good.id, good.title, sum(store.rest) AS storerest, count(pics.id) AS picscount FROM goods LEFT JOIN store ON (goods.id = st

我有三张桌子:货物、商店和图片。在第一个表中存储商品名称。在第二个-不同库存商品的平衡,在第三个-商品图片链接。因此,商品与商店和图片有一对多的联系。 现在,我需要通过一次查询获得一个包含库存余额和图片计数的商品列表。 我是这样做的:

SELECT good.id, good.title, sum(store.rest) AS storerest, count(pics.id) AS picscount 
FROM goods 
LEFT JOIN store ON (goods.id = store.goodid) 
LEFT JOIN pics ON (goods.id = pics.goodid) 
GROUP BY goods.id`
当good有0或1张图片时,一切看起来都正常。但当它有两个storerest双倍的时候,我不明白为什么。
怎么了?

您的问题是,当您有两(或更多)行
存储
和两(或更多)行
图片
用于单个
商品
行时,您最终得到的是所有行组合的乘积

要解决此问题,请在加入之前进行聚合:

SELECT 
  good.id, 
  good.title, 
  IFNULL(s.storerest, 0) AS storerest, 
  IFNULL(p.picscount, 0) AS picscount
FROM goods 
LEFT JOIN (
  SELECT goodid, sum(rest) AS storerest
  FROM store
  GROUP BY goodid
) s ON (goods.id = s.goodid) 
LEFT JOIN (
  SELECT goodid, count(id) AS picscount
  FROM pics
  GROUP BY goodid
) p ON (goods.id = p.goodid) 

首先考虑连接的大小。如果一件商品有两张图片,那么该商品的行数将增加一倍。实际上,除了图片部分,行将被复制。因此,store.rest的总和将两次提取所有内容。使用三张图片,您将获得三倍的输出。

您将表“货物”与其他两个表连接在一起,其中这两个其他表与“货物”表具有一对多关系。当它们合并时,将产生行的组合-因此,如果有2张图片,则存储项将列出两次

解决此问题的最简单方法是,首先计算子表的统计信息,然后将它们连接起来,并在计算唯一项时使用不同计数,因此,例如,您的查询应该是:

SELECT good.id, good.title, sum_rest AS storerest, count(distinct pics.id) AS picscount 
FROM goods 
LEFT JOIN (select goodid, sum(rest) as sum_rest from store) s ON (goods.id = s.goodid) 
LEFT JOIN pics ON (goods.id = pics.goodid) 
GROUP BY goods.id

如果删除GROUP BY子句,您将看到为什么sum(store.rest)不是您所期望的。如果在表
pics
中,对于特定的
pics
goodid
(行)存在多行,那么mysql似乎会为每个
pics
goodid
行创建额外的虚拟行。并插入
goods
store
表中的值,其中
pics
goodid
=
store
goodid
=
goods
。使用
sum(store.rest)
简单地对所有行(包括伪行)求和。这里的一些例子可能有助于理解正在发生的事情。对我来说不那么容易理解…请给我一些建议。使用subselect from
store
靠近左侧的连接,我只选择必要的列,而不是整个表?@user2360831-是的,正如您在上面的回答中所看到的,
store
subselect只使用
goodid
rest
字段,而不关心
store
表的任何其他列(如果有)。