15 游戏玩法分析 III
astak16 opened this issue · comments
题目
查询每组玩家和日期,以及玩家到目前位置玩了多少游戏,也就是说,再此日期之前玩家所玩的游戏总数。
create table activity (
player_id int,
device_id int,
event_date date,
games_played int
);
insert into activity values
(1, 2, '2016-03-01', 5),
(1, 2, '2016-05-02', 6),
(1, 3, '2017-06-25', 1),
(3, 1, '2016-03-02', 0),
(3, 4, '2018-07-03', 5);
SQL:方法一
select player_id, event_date,
sum(
case
when @pre_player_id = player_id then @n:=@n+games_played
when @pre_player_id:= player_id then @n:=games_played
end
) as games_played_so_far
from (
select * from activity order by player_id, event_date
) temp, (select @pre_player_id:=null, @n:=0) init
group by player_id, event_date;
解析
因为最终的结果是计算每个用户在某天玩游戏的次数,所以需要按照 player_id
和 event_date
分组。
因为 order by
执行的顺序在 sum
函数后面执行,所以这里需要先对 player_id
和 event_date
先进行排序。
具体实现:
- 将
activity
按照player_id
和event_date
升序排序,命名为temp
临时表 - 将临时表
temp
按照player_id
和event_date
进行分组 - 使用
case ... when ... then ...end
语句对分组后的temp
中games_played
进行输出,并用sum
求和
SQL:方法二
select
player_id,
event_date,
sum(games_played)
over(partition by player_id order by event_date) as games_played_so_far
from activity;
解析
在 sum
函数后面可以使用 over
对其按照 player_id
分组,并按照 event_date
排序。
SQL:方法三
select a.player_id, a.event_date, sum(b.games_played) as games_played_so_far
from activity a join activity b
on a.player_id = b.player_id where a.event_date >= b.event_date
group by a.player_id, a.event_date;
解析
- 将表
activity
自连,连接条件a.player_id = b.player_id
筛选出a.event_date >= b.event_date
- 按照
a
表的player_id
和a.event_date
进行分组 - 在求和的时候,使用的是
b.games_played
- 因为筛选条件是
a.event_date >= b.event_date
也就是说在a.event_date >= b.event_date
的数据中,a.games_played
都是一样的,是不对的。
- 因为筛选条件是