在同一查询中使用 SUM 和 DISTINCT

Posted

技术标签:

【中文标题】在同一查询中使用 SUM 和 DISTINCT【英文标题】:using SUM and DISTINCT in the same query 【发布时间】:2013-10-03 07:51:26 【问题描述】:

因此,我正在尝试构建一个查询,该查询将向我显示对于每种类型的活动,哪些用户的得分最高。您可以在下面看到表格结构。每个活动都有一个activity_typeid,每个活动都有一个特定的activity_weight

在下面的示例中,Bob 的通话得分为 50 分,会议得分为 100 分。詹姆斯在通话中得到 100 分,在会议中得到 100 分。

userid     activity_typeid     activity_weight
------------------------------------------------------------
123 (Bob)  8765 (calls)                50
123 (Bob)  8121 (meetings)             100
431 (James) 8765 (calls)               50
431 (James) 8121 (meetings)            100
431 (James) 8765 (calls)               50

我希望能够输出以下内容:

    通话表现最佳 = 詹姆斯 会议表现最佳者 = Bob, James。

我事先不知道 activity_typeid,因为它们是随机输入的,所以我想知道是否可以构建某种查询来计算每个 DISTINCT/UNIQUE activity_typeid 的总和?

提前非常感谢。

【问题讨论】:

为什么(James)(呼叫)在您的表中重复? 对不起,我应该解释得更好。每次执行此操作(调用)时,都会在此表中输入一个新条目。因此,他的总分又增加了 50 分。所以说这不是重复的。 现在看,你说,詹姆斯有 100 分的电话 = 50 + 50 您能否提供此表的 SQL 代码和 SQLFiddle 上的示例数据,以便人们检查他们的答案。加上所需的输出。 【参考方案1】:

你需要的是解析函数DENSE_RANK()。如果每个活动都需要表现最好的人,一种方法

SELECT a.activity_typeid, GROUP_CONCAT(a.userid) userid
  FROM
(
  SELECT activity_typeid, userid, SUM(activity_weight) activity_weight
    FROM table1
  -- WHERE ...
   GROUP BY userid, activity_typeid
) a JOIN 
(
  SELECT activity_typeid, MAX(activity_weight) activity_weight
    FROM
  (
    SELECT activity_typeid, userid, SUM(activity_weight) activity_weight
      FROM table1
      -- WHERE ...
     GROUP BY userid, activity_typeid
  ) q
   GROUP BY activity_typeid
) b 
    ON a.activity_typeid = b.activity_typeid
   AND a.activity_weight = b.activity_weight
 GROUP BY activity_typeid

mysql 中模拟 DENSE_RANK() 的另一种方法是利用会话变量

SELECT activity_typeid, GROUP_CONCAT(userid) userid
  FROM
(
  SELECT activity_typeid, userid, activity_weight,
         @n := IF(@g = activity_typeid, IF(@v = activity_weight, @n, @n + 1) , 1) rank,
         @g := activity_typeid, @v := activity_weight
    FROM
  (
    SELECT activity_typeid, userid, 
           SUM(activity_weight) activity_weight
      FROM table1
    -- WHERE ...
     GROUP BY activity_typeid, userid
  ) q CROSS JOIN (SELECT @n := 0, @g := NULL, @v := NULL) i
     ORDER BY activity_typeid, activity_weight DESC, userid
) q
 WHERE rank = 1
 GROUP BY activity_typeid

输出:

| ACTIVITY_TYPEID |用户名 | |-----------------|---------| | 8121 | 123,431 | | 8765 |第431章

这是 SQLFiddle 两个查询的演示

【讨论】:

如果我想添加 WHERE 子句,我应该在 a、b 和 c 中添加它还是只在末尾添加一次? @user2656127 不客气 :) 查看更新的答案。您希望两个 WHERE 子句相同。 非常感谢您的精彩回答。如果我可以再用一件事打扰你。我希望在这里运行 1 个额外的连接,主要是为了使用用户 ID 从用户表中获取用户名。我应该把它放在最后吗?此外,此代码是否适用于表中无限数量的 activity_typeid(即驱动 10 种不同类型活动的竞赛),还是仅适用于一组数字?再次感谢:D @user2656127 您只需要用户名还是还需要用户 ID? 好吧,我将使用 userid 加入 users 表来选择 name 和 profilepicture。【参考方案2】:

您必须使用GROUP BY 语句来计算每个用户和每个活动类型ID 的总和。试试这样的:

SELECT userid, activity_typeid, SUM(activity_weight)
FROM table
GROUP BY userid, activity_typeid

然后将其用作子查询来确定每个 activity_typeid 的最佳执行者。

【讨论】:

是的,子查询是我需要一点帮助的地方。有小费吗?谢谢! 看看这个:***.com/questions/12113699/…【参考方案3】:

如果你想使用聚合函数,你需要使用GROUP BY,而不是DISTINCT。您可以按useridactivity_typeid 分组,然后选择SUM(activity_weight)

【讨论】:

【参考方案4】:

当然,只要像这样使用 group by :

SELECT t.userid, t.activity_typeid, sum(t.activity_weight) 
FROM YOURTABLE t
GROUP BY t.userid, t.activity_typeid

【讨论】:

【参考方案5】:

查询以选择给定活动的(单个)表现最佳者:

SELECT userid, activity_typeid, SUM(activity_weight)
FROM ?
WHERE activity_typeid = ?
GROUP BY userid
ORDER BY SUM(activity_weight) DESC
LIMIT 1

您可以更改 LIMIT 以输出前 5 或 10 名表演者,然后在代码中检查它们以查看您要显示的内容(例如,如果两个人的分数相同)。

【讨论】:

谢谢!问题是 WHERE activity_typeid = ?这就是我不确定如何解决的问题,因为我不知道,并且想遍历该表中的所有 id(其中一个 id 匹配) 当您知道activity_typeid 时,您知道可以在运行时构建查询吗?查找“参数化查询”以了解如何轻松完成。

以上是关于在同一查询中使用 SUM 和 DISTINCT的主要内容,如果未能解决你的问题,请参考以下文章

在同一个 SQL 查询中运行正常的 pull 和 sum()

在同一个 SELECT sql 查询中从 SUM() 计算百分比

在另一个查询 MySQL 中使用一个查询的 SUM

同一查询中的火花计数和过滤计数

数据库--查询--按小时查询&在where里面使用sum函数

sum()在具有多个联接的MySQL查询中不能正常工作(group by不能按预期工作)