题目描述
(通过次数9,381 | 提交次数12,628,通过率74.29%)
表: Scores +---------------+---------+ | Column Name | Type | +---------------+---------+ | player_name | varchar | | gender | varchar | | day | date | | score_points | int | +---------------+---------+ (gender, day)是该表的主键 一场比赛是在女队和男队之间举行的 该表的每一行表示一个名叫 (player_name) 性别为 (gender) 的参赛者在某一天获得了 (score_points) 的分数 如果参赛者是女性,那么 gender 列为 'F',如果参赛者是男性,那么 gender 列为 'M' 写一条SQL语句查询每种性别在每一天的总分。 返回按gender和day对查询结果 升序排序的结果。 查询结果格式的示例如下。 示例 1: 输入: Scores表: +-------------+--------+------------+--------------+ | 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 | +-------------+--------+------------+--------------+ 输出: +--------+------------+-------+ | 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 | +--------+------------+-------+ 解释: 女性队伍: 第一天是 2019-12-30,Priyanka 获得 17 分,队伍的总分是 17 分 第二天是 2019-12-31, Priya 获得 23 分,队伍的总分是 40 分 第三天是 2020-01-01, Aron 获得 17 分,队伍的总分是 57 分 第四天是 2020-01-07, Alice 获得 23 分,队伍的总分是 80 分 男性队伍: 第一天是 2019-12-18, Jose 获得 2 分,队伍的总分是 2 分 第二天是 2019-12-25, Khali 获得 11 分,队伍的总分是 13 分 第三天是 2019-12-30, Slaman 获得 13 分,队伍的总分是 26 分 第四天是 2019-12-31, Joe 获得 3 分,队伍的总分是 29 分 第五天是 2020-01-07, Bajrang 获得 7 分,队伍的总分是 36 分 来源:力扣(LeetCode) 链接:https://leetcode.cn/problems/running-total-for-different-genders
--测试数据 Create table If Not Exists Scores (player_name varchar(20), gender varchar(1), day date, score_points int); insert into Scores (player_name, gender, day, score_points) values ('Aron', 'F', '2020-01-01', '17'); insert into Scores (player_name, gender, day, score_points) values ('Alice', 'F', '2020-01-07', '23'); insert into Scores (player_name, gender, day, score_points) values ('Bajrang', 'M', '2020-01-07', '7'); insert into Scores (player_name, gender, day, score_points) values ('Khali', 'M', '2019-12-25', '11'); insert into Scores (player_name, gender, day, score_points) values ('Slaman', 'M', '2019-12-30', '13'); insert into Scores (player_name, gender, day, score_points) values ('Joe', 'M', '2019-12-31', '3'); insert into Scores (player_name, gender, day, score_points) values ('Jose', 'M', '2019-12-18', '2'); insert into Scores (player_name, gender, day, score_points) values ('Priya', 'F', '2019-12-31', '23'); insert into Scores (player_name, gender, day, score_points) values ('Priyanka', 'F', '2019-12-30', '17');
解题思路
这道题在题目上其实有些描述不太准确的地方。
首先,题目里描述scores表的主键是(gender, day),但实际上,表里还有一个player_name的字段,难道每天同一个性别只有一个player(当然题目中给出的样例数据确实是这样,虽然跟实际情况可能不太相符)?
所以,相对来说,scores表的主键是(player_name, day)会比较合理一些。而gender仅仅是player_name的一个属性而已。
其次,题目要求计算“每种性别在每一天的总分”。根据题目下面的解释,可以知道,这个“总分”,其实是从最开始日期累计到当天的总分,而不仅仅是当天的分数加总。
基于以上两点,我们再来看这道题。
源表scores的主键是(player_name, day),结果数据的主键是(gender, day)。而同一个gender下可能会存在多个player_name,所以,在计算上,需要做一次group by汇总操作。
简单来看,如果仅仅是计算每天每个性别的总分,那直接使用下面的SQL语句就可以了。
select gender,day,sum(score_points) as total from scores group by gender,day order by gender,day;
但题目实际上要求的是计算累计值,即:最开始的那一天到现在的累计总分。
关于累计的计算,在SQL编写的过程中,其实是一个比较经典,也比较常见的需求。常见于各类分析报表中。
思路上,一般来说,都是先构造出一个累加到每天的明细数据,然后再分组汇总即可。
具体到这道题,上面的SQL已经计算出了每天每个gender的汇总值,那么再将每一天的数据发散到所有比它大的日期上,最后再以gender+day分组汇总即可。
参考SQL
未特别说明的情况下,参考SQL为基于MySQL8.0实现。
with total_score as ( select gender,day,sum(score_points) as total from scores group by gender,day order by gender,day ) select a.gender, a.day, sum(b.total) as total from total_score a inner join total_score b on a.gender = b.gender and a.day >= b.day group by a.gender,a.day order by a.gender,a.day;
本站所有内容均为原创,本站保留所有权利。仅允许非商业用途的转载,但必须注明来源网站、作者、来源链接!否则,由此造成的一切后果,由转载方承担!
干货分享、技术提升、面试笔试、学习交流,欢迎关注公众号:xuesql。QQ学习交流群:209942678。