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 fromstore
靠近左侧的连接,我只选择必要的列,而不是整个表?@user2360831-是的,正如您在上面的回答中所看到的,store
subselect只使用goodid
和rest
字段,而不关心store
表的任何其他列(如果有)。