Mysql疑难题的记录(力扣)
534. 游戏玩法分析 III(求累加值)
sql架构
Create table If Not Exists Activity (player_id int, device_id int, event_date date, games_played int) Truncate table Activity insert into Activity (player_id, device_id, event_date, games_played) values ('1', '2', '2016-03-01', '5') insert into Activity (player_id, device_id, event_date, games_played) values ('1', '2', '2016-05-02', '6') insert into Activity (player_id, device_id, event_date, games_played) values ('1', '3', '2017-06-25', '1') insert into Activity (player_id, device_id, event_date, games_played) values ('3', '1', '2016-03-02', '0') insert into Activity (player_id, device_id, event_date, games_played) values ('3', '4', '2018-07-03', '5')
这张表显示了某些游戏的玩家的活动情况。
每一行是一个玩家的记录,他在某一天使用某个设备注销之前登录并玩了很多游戏(可能是 0 )
问题:
编写一个 SQL 查询,同时报告每组玩家和日期,以及玩家到目前为止玩了多少游戏。也就是说,在此日期之前玩家所玩的游戏总数。
Result table: +-----------+------------+---------------------+ | player_id | event_date | games_played_so_far | +-----------+------------+---------------------+ | 1 | 2016-03-01 | 5 | | 1 | 2016-05-02 | 11 | | 1 | 2017-06-25 | 12 | | 3 | 2016-03-02 | 0 | | 3 | 2018-07-03 | 5 | +-----------+------------+---------------------+ 对于 ID 为 1 的玩家,2016-05-02 共玩了 5+6=11 个游戏,2017-06-25 共玩了 5+6+1=12 个游戏。 对于 ID 为 3 的玩家,2018-07-03 共玩了 0+5=5 个游戏。 请注意,对于每个玩家,我们只关心玩家的登录日期。
解法1:
select t1.player_id,t1.event_date,sum(t2.games_played) games_played_so_far from Activity t1 inner join Activity t2 on t1.player_id = t2.player_id and t1.event_date >= t2.event_date group by t1.player_id,t1.event_date order by t1.player_id,t1.event_date
思路:
我们求的是每个玩家从第一天开始,到最后一天结束。每天统计:当天玩游戏次数+之前的所有天的玩游戏次数的总和。
首先,使用笛卡尔积,自连2个表。
然后,条件筛选,t1.event_date >= t2.event_date。⚠️这个条件非常重要!理解它就理解了本题答案。
- t1.event_date > t2.event_date:
-
- 如果t1.event_date是day_one,那么筛选表中只有一条数据是关于t1.day_one的。
- 如果t1.event_date是day_two, 那么筛选表中会有2行相关t1.day_two的数据,这两行数据的区别在t2.event_date: 一个是day_one, 一个是day_two.
- 如果t1.event_date是day_three,那么筛选表中会有3行相关t1.day_three的数据。。。
- 同理可知之后的情况。
那么,以t1.even_date进行分组的话,sum(t2.games_played)就相当于累加了当天及之前数天的玩游戏的次数。
总结:
扫描二维码关注公众号,回复:
8519024 查看本文章
将每个人,在当前和之前几天玩过的游戏个数进行累加。
2个表自连接,筛选条件,group by。 使用累加和的方法解题。
另一种解法:
使用Mysql8.0的window计算函数。
select player_id, event_date, sum(games_played) over(partition by player_id order by event_date asc rows UNBOUNDED PRECEDING ) as games_played_so_far from activity;
+-----------+------------+---------------------+ | player_id | event_date | games_played_so_far | +-----------+------------+---------------------+ | 1 | 2016-03-01 | 5 | | 1 | 2016-05-02 | 11 | | 1 | 2017-06-25 | 12 | | 3 | 2016-03-02 | 0 | | 3 | 2018-07-03 | 5 | +-----------+------------+---------------------+
window的frame语法使用:https://www.cnblogs.com/chentianwei/p/12145280.html
⬆️代码也可以用
- range UNBOUNDED PRECEDING
- range between UNBOUNDED PRECEDING and current row
- rows between UNBOUNDED PRECEDING and current row
⚠️好像range|rows是别名的关系。
更复杂的方法:
使用if语句和@var进行逻辑判断和逻辑运算。不适合mysql5.7。分析不复杂,但代码写起来很复杂。