【问题标题】:How to group summed up columns from different tables?如何对来自不同表的汇总列进行分组?
【发布时间】:2011-03-12 01:40:10
【问题描述】:

我有一个用户表 (User) 和 3 个教程表(文本、视频和其他)。

每个教程都有rating_positiverating_negative 列 并链接到用户 (id)。

我想选择教程最多的10个用户和总和 他们的教程的正面/负面评价。

我尝试了以下查询,但它不起作用。它为 tutorials_count/pos/neg 返回太多结果。我怎样才能正确地做到这一点?

SELECT  
    u.id AS user_id,  
    (COUNT(t.id) + COUNT(v.id) + COUNT(o.id)) AS tutorials_count,
    (SUM(t.rating_positive) + SUM(v.rating_positive) + SUM(o.rating_positive)) AS pos,
    (SUM(t.rating_negative) + SUM(v.rating_negative) + SUM(o.rating_negative)) AS neg
FROM
    user u LEFT JOIN trick t ON u.id = t.submitter_id
    LEFT JOIN video v ON u.id = v.submitter_id
    LEFT JOIN other o ON u.id = o.submitter_id
GROUP BY u.id
ORDER BY tutorials_count DESC
LIMIT 10

【问题讨论】:

    标签: mysql join sum


    【解决方案1】:

    尝试使用您感兴趣的三个表的 UNION ALL 进行子查询,然后加入:

    SELECT  
        u.id AS user_id,  
        COUNT(submitter_id) AS tutorials_count,
        IFNULL(SUM(rating_positive), 0) AS pos,
        IFNULL(SUM(rating_negative), 0) AS neg
    FROM user u
    LEFT JOIN (
        SELECT submitter_id, rating_positive, rating_negative FROM trick
        UNION ALL
        SELECT submitter_id, rating_positive, rating_negative FROM video
        UNION ALL
        SELECT submitter_id, rating_positive, rating_negative FROM other
    ) T1
    ON u.id = T1.submitter_id
    GROUP BY u.id
    ORDER BY tutorials_count DESC
    LIMIT 10
    

    【讨论】:

    • 这行得通。 :-) 有没有更好的查询性能更快?
    【解决方案2】:

    LEFT JOIN 很好,并且比在执行聚合之前联合所有三个表的性能更好。

    问题是 LEFT JOIN 上的 SUMmation 意味着结果可能为 NULL,您不能将其与其他列的总和一起添加。即:

    ... SUM(t.rating_positive) + 1
    

    ...如果SUM(t.rating_positive) 没有支持记录,将返回 NULL,因为 NULL + 1 等于 NULL。

    您需要使用 COALESCE 将这些值转换为零才能进行数学运算 - IFNULL 是一种可接受的替代方案,但它是 MySQL 特定的,因此不太可能是可移植的:

       SELECT u.id AS user_id,  
              COALESCE(COUNT(t.id), 0) + COALESCE(COUNT(v.id), 0) + COALESCE(COUNT(o.id), 0) AS tutorials_count,
              COALESCE(SUM(t.rating_positive), 0) + COALESCE(SUM(v.rating_positive), 0) + COALESCE(SUM(o.rating_positive), 0) AS pos,
              COALESCE(SUM(t.rating_negative), 0) + COALESCE(SUM(v.rating_negative), 0) + COALESCE(SUM(o.rating_negative), 0) AS neg
         FROM USER u 
    LEFT JOIN trick t ON u.id = t.submitter_id
    LEFT JOIN video v ON u.id = v.submitter_id
    LEFT JOIN other o ON u.id = o.submitter_id
     GROUP BY u.id
     ORDER BY tutorials_count DESC
        LIMIT 10
    

    【讨论】:

    • 这将返回与没有 COALESCE 时相同(错误)的值
    • 这和 UNION 版本是等价的 - UNION 只是不再需要在每个表的基础上捕获 NULL,所以我能想到的唯一可能是您简化了查询详细信息并且无法协调这些使用我提供的查询。
    猜你喜欢
    • 1970-01-01
    • 2021-12-26
    • 1970-01-01
    • 1970-01-01
    • 2020-12-23
    • 2019-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多