17

I have 3 tables: goods, store and pics. In the first table goods titles are stored. In the second - balance of goods in different stocks, in the third - links to goods pictures. So goods has one-to-many connection with store and pics. Now, I need to get a list of goods with sum of stock rests and count of pictures by one query. I did it like this:

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`

All seems ok while good has 0 or 1 picture. But when it has 2 - storerest doubles, and I can't understand why. What's wrong?

4

3 回答 3

30

您的问题是,当您有两行(或更多)store行和两行(或更多)pics行时goods,您最终会得到所有行组合的乘积。

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

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) 
于 2013-02-19T20:56:26.730 回答
3

您正在将表“商品”与其他两个表连接在一起,其中这两个其他表与“商品”表具有一对多的关系。当它们加入时,将产生行组合 - 因此,如果有 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
于 2013-02-19T21:01:57.280 回答
2

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

于 2013-02-19T20:58:07.133 回答