Mysql疑难题的记录(力扣)

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:
    1. 如果t1.event_date是day_one,那么筛选表中只有一条数据是关于t1.day_one的。
    2. 如果t1.event_date是day_two,  那么筛选表中会有2行相关t1.day_two的数据,这两行数据的区别在t2.event_date: 一个是day_one, 一个是day_two.
    3. 如果t1.event_date是day_three,那么筛选表中会有3行相关t1.day_three的数据。。。
    4. 同理可知之后的情况。

那么,以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。分析不复杂,但代码写起来很复杂。

猜你喜欢

转载自www.cnblogs.com/chentianwei/p/12179445.html