高级农民
- 积分
- 4176
- 大米
- 颗
- 鳄梨
- 个
- 水井
- 尺
- 蓝莓
- 颗
- 萝卜
- 根
- 小米
- 粒
- 学分
- 个
- 注册时间
- 2017-1-22
- 最后登录
- 1970-1-1
|
1308. Running Total for Different Genders
Medium
Topics
SQL Schema
Pandas Schema
Table: Scores
+---------------+---------+
| Column Name | Type |
+---------------+---------+
| player_name | varchar |
| gender | varchar |
| day | date |
| score_points | int |
+---------------+---------+
(gender, day) is the primary key (combination of columns with unique values) for this table.
A competition is held between the female team and the male team.
Each row of this table indicates that a player_name and with gender has scored score_point in someday.
Gender is 'F' if the player is in the female team and 'M' if the player is in the male team.
Write a solution to find the total score for each gender on each day.
Return the result table ordered by gender and day in ascending order.
The result format is in the following example.
Example 1:
Input:
Scores table:
+-------------+--------+------------+--------------+
| 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 |
+-------------+--------+------------+--------------+
Output:
+--------+------------+-------+
| 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 |
+--------+------------+-------+
Explanation:
For the female team:
The first day is 2019-12-30, Priyanka scored 17 points and the total score for the team is 17.
The second day is 2019-12-31, Priya scored 23 points and the total score for the team is 40.
The third day is 2020-01-01, Aron scored 17 points and the total score for the team is 57.
The fourth day is 2020-01-07, Alice scored 23 points and the total score for the team is 80.
For the male team:
The first day is 2019-12-18, Jose scored 2 points and the total score for the team is 2.
The second day is 2019-12-25, Khali scored 11 points and the total score for the team is 13.
The third day is 2019-12-30, Slaman scored 13 points and the total score for the team is 26.
The fourth day is 2019-12-31, Joe scored 3 points and the total score for the team is 29.
The fifth day is 2020-01-07, Bajrang scored 7 points and the total score for the team is 36.
思路
这是经典的**累计求和(running total)**问题:每个性别各自按日期排序,每一天的 total 是该性别从最早一天到当天的得分之和。
有两点要抓住:
按性别分开累计:男队和女队互不影响,所以要对 gender 分区。
不需要先分组汇总:(gender, day) 是主键,同一性别同一天只有一行,所以每行的 score_points 就是当天的得分,直接累计即可。- # Write your MySQL query statement below
- SELECT
- gender,
- day,
- SUM(score_points) OVER (
- PARTITION BY gender
- ORDER BY day
- ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
- ) AS total
- FROM Scores
- ORDER BY gender, day;
复制代码 逐步解释
PARTITION BY gender:男女各算各的,累计到另一个性别时重新从 0 开始。
ORDER BY day:在每个分区内按日期从早到晚排序,决定"累计到哪一天"。
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW:窗口从分区第一行到当前行。这其实就是加了 ORDER BY 之后的默认行为,显式写出来是为了意图更清楚。因为 (gender, day) 唯一,用 ROWS 和默认的 RANGE 结果一致。
外层 ORDER BY gender, day:窗口函数里的 ORDER BY 只决定累计顺序,不保证输出顺序,所以最后仍要显式排序。
SQL 解法二:自连接(不依赖窗口函数)- SELECT
- a.gender,
- a.day,
- SUM(b.score_points) AS total
- FROM Scores a
- JOIN Scores b
- ON a.gender = b.gender
- AND b.day <= a.day
- GROUP BY a.gender, a.day
- ORDER BY a.gender, a.day;
复制代码 对每一行 a,找出同性别且日期不晚于它的所有行 b,也就是"从最早到今天"的所有记录。
对这些行的得分求和,就是累计总分。
自连接会产生大约 N² / 2 级别的中间行,数据量大时比窗口函数慢,只适合不支持窗口函数的环境。 |
|