【问题标题】:MySQL: SUM(CASE WHEN(...)) + GROUP BY. Why details of dataset cannot show even with GROUP BY?MySQL:总和(案例时(...))+ 分组。为什么即使使用 GROUP BY 也无法显示数据集的详细信息?
【发布时间】:2020-10-28 01:24:18
【问题描述】:

Credit: Leetcode 1308. Running Total for different Genders

样本分数表:

+-------------+--------+------------+--------------+
| player_name | gender | day        | score_points |
+-------------+--------+------------+--------------+
| Aron        | F      | 2020-01-01 | 17           |
| Alice       | F      | 2020-01-07 | 23           |
| Bajrang     | M      | 2020-01-07 | 7            |
| Khali       | M      | 2019-12-25 | 11           |
| Slaman      | M      | 2019-12-30 | 13           |
| Joe         | M      | 2019-12-31 | 3            |
| Jose        | M      | 2019-12-18 | 2            |
| Priya       | F      | 2019-12-31 | 23           |
| Priyanka    | F      | 2019-12-30 | 17           |
+-------------+--------+------------+--------------+

要求:编写一个 SQL 查询来查找每个性别每天的(累积)总分。 按性别和日期对结果表进行排序。示例结果表如下:

+--------+------------+-------+
| gender | day        | total |
+--------+------------+-------+
| F      | 2019-12-30 | 17    |
| F      | 2019-12-31 | 40    |
| F      | 2020-01-01 | 57    |
| F      | 2020-01-07 | 80    |
| M      | 2019-12-18 | 2     |
| M      | 2019-12-25 | 13    |
| M      | 2019-12-30 | 26    |
| M      | 2019-12-31 | 29    |
| M      | 2020-01-07 | 36    |
+--------+------------+-------+

我的代码如下。我不明白为什么它只返回一行[{"headers": ["gender", "day", "total"], "values": [["F", "2019-12-30", 184] ]}],即使使用 GROUP BY。

SELECT s1.gender, s1.day, 
SUM(CASE WHEN s1.day < s2.day AND s1.gender = s2.gender THEN s1.score_points ELSE 0 END) AS total
FROM Scores s1, Scores s2
GROUP BY s1.gender AND s1.day
ORDER BY s1.gender AND s1.day

如果有人可以帮助我,非常感谢!

【问题讨论】:

  • 指定 MySQL 版本。
  • 要求:编写一个 SQL 查询,找出每个性别每天的总分。 ... 示例结果表如下: 显示的结果是累积和。

标签: mysql sql group-by sum case-when


【解决方案1】:

您应该使用ON 子句进行正确连接,并为GROUP BYORDER BY 使用有效语法:

select s1.gender, s1.day, sum(s2.score_points) total
from scores s1 inner join scores s2
on s2.gender = s1.gender and s2.day <= s1.day
group by s1.gender, s1.day
order by s1.gender, s1.day

请参阅demo
结果:

| gender | day        | total |
| ------ | -----------| ----- |
| F      | 2019-12-30 | 17    |
| F      | 2019-12-31 | 40    |
| F      | 2020-01-01 | 57    |
| F      | 2020-01-07 | 80    |
| M      | 2019-12-18 | 2     |
| M      | 2019-12-25 | 13    |
| M      | 2019-12-30 | 26    |
| M      | 2019-12-31 | 29    |
| M      | 2020-01-07 | 36    |

【讨论】:

    【解决方案2】:

    我不确定这是否有效,但它会通过:

    SELECT T1.gender, T1.day, SUM(T2.score_points) AS total
    FROM Scores T1
    JOIN Scores T2
    WHERE T1.gender = T2.gender AND T2.day <= T1.day
    GROUP BY T1.gender, t1.day
    ORDER BY t1.gender, t1.day;
    

    参考文献

    • 有关其他详细信息,您可以查看Discussion Board。有很多公认的解决方案,有各种languages 和解释、高效的算法,以及渐近的time/space 复杂性分析1, 2

    【讨论】:

    • 感谢您的建议!我确实在那里看到了很多很棒的答案,但想知道为什么我错了。现在一切都解决了。谢谢!
    【解决方案3】:

    AND 是返回真/假 (1/0) 的布尔运算。您似乎想要条件聚合:

    SELECT s.day, 
           SUM(CASE WHEN s.gender = 'M' THEN s.score_points ELSE 0 END) AS total_male,
           SUM(CASE WHEN s.gender = 'F' THEN s.score_points ELSE 0 END) AS total_female
    FROM Scores s
    GROUP BY s.day
    ORDER BY s.day;
    

    GROUP BY 键确定结果集的外观。每组唯一值在结果集中都有一行,其余列汇总以适合该行。

    在这种情况下,您需要每天一行,所以这应该是 GROUP BY 中的内容。

    那么对于累计量使用窗口函数:

    SELECT s.day, 
           SUM(CASE WHEN s.gender = 'M' THEN s.score_points ELSE 0 END) AS total_male,
           SUM(CASE WHEN s.gender = 'F' THEN s.score_points ELSE 0 END) AS total_female,
           SUM(SUM(CASE WHEN s.gender = 'M' THEN s.score_points ELSE 0 END)) OVER (ORDER BY s.day) AS running_male,
           SUM(CASE WHEN s.gender = 'F' THEN s.score_points ELSE 0 END) OVER (ORDER BY s.day) AS running_female
    FROM Scores s
    GROUP BY s.day
    ORDER BY s.day;
    

    【讨论】:

    • 我看到了我使用 group by 的问题。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多