2011-06-27 38 views
2

我有几个表在我的应用程序中使用。一个维护一个产品列表,另一个维护对这些项目的评论,另一个包含这些项目的星级评分,最后一个购买这些项目。我的表是这个样子:需要查询帮助 - 聚合和多个连接

tbl_item: 
--------- 
id  INT (primary key) 
name VARCHAR (product name) 

tbl_comment: 
------------ 
id   INT (primary key) 
item_id  INT (foregin key -> tbl_item.id) 
commenttext VARCHAR 

tbl_rating: 
----------- 
id   INT (primary key) 
item_id  INT (foreign key -> tbl_item.id) 
rating  DOUBLE 

tbl_purchases: 
-------------- 
id   INT (primary key) 
item_id  INT (foreign key -> tbl_item.id) 

我想执行返回下面的查询:

* The design ID 
* The average rating 
* The number of comments 
* The number of purchases 

我有一些与此类似,但它返回不正确的数据:

SELECT d.id , 
     COUNT(tbl_purchases.id) AS purchase_count, 
     COUNT(tbl_comment.id) AS comment_count, 
     AVG(tbl_rating.rating) AS item_rating, 
    FROM tbl_item d 
    LEFT JOIN tbl_purchases ON tbl_purchases.item_id = d.id 
    LEFT JOIN tbl_comment ON tbl_comment.item_id = d.id 
    LEFT JOIN tbl_rating ON tbl_rating.id = d.id 
    GROUP BY d.id; 

我发现我的COUNT()列为两列返回相同的值,这肯定是不正确的。很明显,我在我的连接或GROUP BY中做错了事,但我不完全确定是什么。我是一个Java人,而不是一个SQL人,所以我不确定这个SELECT语句出了什么问题。

任何人都可以帮我构建这个查询吗?有没有办法通过这种方式跨多个不同的表执行这个聚合查询?谢谢!!

+0

计数将返回相同,因为它计数最终结果集(它不关心它是否为空)。如果你想每桌单独计数,我建议看看子查询。 – Limey

+0

您也可以设置变量,然后用case语句手动跟踪每个表的总计。 – Limey

+0

你能给我一个例子,说明如何用子查询来完成这个任务吗?就像我说的,我是一个Java人,并且对SQL没有太多的经验。 – Shadowman

回答

5

试试这个:

SELECT d.id , 
     COALESCE(t.purchase_count,0) as purchase_count, 
     COALESCE(c.comment_count,0) as comment_count, 
     r.item_rating, 
    FROM tbl_item d 
    LEFT JOIN (SELECT item_id, COUNT(1) as purchase_count from tbl_purchases group by item_id) as t on t.item_id = d.id 
    LEFT JOIN (SELECT item_id, COUNT(1) as comment_count from tbl_comment group by item_id) as c ON c.item_id = d.id 
    LEFT JOIN (SELECT item_id, AVG(rating) as item_rating from tbl_rating group by item_id) as r ON r.item_id = d.id; 
+0

打我吧:) +1 – Randy

+0

我试了@Seth Robertson的答案,它的工作,但表现很糟糕。这个答案效果很好。数量级更快。谢谢! – Shadowman

+0

作为一个经验法则,在连接之前而不是在连接之后实现一个组总是最好的。如果你考虑数据库必须做什么来执行一个组和一个连接,你会明白为什么这是真的(我没有足够的空间来提供解释:))。 – Gareth

0

这将取决于上有所DB你使用的是什么,但在PostgreSQL的这种失控的工作:

SELECT d.id , p.count, c.count, AVG(I.rating) 
     FROM tbl_item d 
     JOIN (SELECT count(id), item_id as id from tbl_purchases) as P 
    USING (id) 
     JOIN (SELECT count(id), item_id as id from tbl_comment) as C 
    USING (id) 
LEFT JOIN tbl_rating as I 
     ON tbl_rating.id = d.id 
    GROUP BY d.id 
; 
1

使用count(distinct(tbl_purchases.id))应该解决您的问题没有更多复杂的查询(但也是正确的)他人提供的查询。

+0

这就像一个魅力!谢谢! – Shadowman

+0

我已经运行这个查询,它工作得很好。但是,我注意到性能是可怕的。其他答案是否会导致查询更快?有什么方法可以获得更好的表现吗? – Shadowman