【问题标题】:Query help needed -- aggregates and multiple joins需要查询帮助——聚合和多个连接
【发布时间】:2011-09-23 18:43:53
【问题描述】:

我的应用程序中使用了几个表。一个维护产品列表,另一个维护这些项目的 cmets,另一个包含这些项目的星级,最后一个包含这些项目的购买。我的表格看起来像这样:

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 语句出了什么问题。

谁能帮我构建这个查询?有没有办法以这种方式跨多个不同的表执行此聚合查询?谢谢!!

【问题讨论】:

  • 计数将返回相同的值,因为它正在计算最终结果集(它不关心它是否为空)。如果您希望每个表单独计数,我建议您查看子查询。
  • 您还可以设置变量,然后使用案例语句手动跟踪每个表的总数。
  • 你能给我一个例子来说明我将如何用子查询来完成这个吗?就像我说的,我是一名 Java 人,对 SQL 的经验并不丰富。

标签: sql postgresql join count aggregate


【解决方案1】:

使用count(distinct(tbl_purchases.id)) 应该可以解决您的问题,而无需其他人提供的更复杂的查询(但也是正确的)。

【讨论】:

  • 我已经运行了这个查询并且效果很好。但是,我注意到性能很糟糕。其他任何答案会导致更快的查询吗?有什么办法可以提高性能?
【解决方案2】:

这在一定程度上取决于您使用的数据库,但这在 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
;

【讨论】:

    【解决方案3】:

    试试这个:

    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;
    

    【讨论】:

    • 我尝试了@Seth Robertson 的答案,它奏效了,但性能很糟糕。这个答案很好用。快几个数量级。谢谢!
    • 根据经验,最好在加入之前而不是之后实现 group by。如果您考虑数据库必须做什么来执行 group by 和 join,您就会明白为什么这是真的(我没有足够的空间来提供解释:))。
    猜你喜欢
    • 1970-01-01
    • 2018-07-18
    • 1970-01-01
    • 2023-03-20
    • 1970-01-01
    • 1970-01-01
    • 2012-02-28
    • 1970-01-01
    • 2020-09-08
    相关资源
    最近更新 更多