1. 程式人生 > 其它 >SQL:511. 遊戲玩法分析 1-5

SQL:511. 遊戲玩法分析 1-5

來源:力扣(LeetCode)
連結:https://leetcode-cn.com/problems/game-play-analysis-iv
著作權歸領釦網路所有。商業轉載請聯絡官方授權,非商業轉載請註明出處。

測試資料

活動表 Activity:

±-------------±--------+
| Column Name | Type |
±-------------±--------+
| player_id | int |
| device_id | int |
| event_date | date |
| games_played | int |

±-------------±--------+
表的主鍵是 (player_id, event_date)。
這張表展示了一些遊戲玩家在遊戲平臺上的行為活動。
每行資料記錄了一名玩家在退出平臺之前,當天使用同一臺裝置登入平臺後開啟的遊戲的數目(可能是 0 個)。

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 ('2', '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');

1. 遊戲玩法 1

寫一條 SQL 查詢語句獲取每位玩家 第一次登陸平臺的日期。

查詢結果的格式如下所示:

Activity 表:
+-----------+-----------+------------+--------------+
| player_id | device_id | event_date | games_played |
+-----------+-----------+------------+--------------+
| 1         | 2         | 2016-03-01 | 5            |
| 1         | 2         | 2016-05-02 | 6            |
| 2         | 3         | 2017-06-25 | 1            |
| 3         | 1         | 2016-03-02 | 0            |
| 3         | 4         | 2018-07-03 | 5            |
+-----------+-----------+------------+--------------+

Result 表:
+-----------+-------------+
| player_id | first_login |
+-----------+-------------+
| 1         | 2016-03-01  |
| 2         | 2017-06-25  |
| 3         | 2016-03-02  |
+-----------+-------------+

連結:https://leetcode-cn.com/problems/game-play-analysis-i

  • 直接通過rank獲取個人的最小時間即可
with t as (
    select player_id, event_date, rank() over (PARTITION BY player_id ORDER BY event_date) as rk from activity
)
select player_id, event_date as first_login from t
where rk = 1;

image-20210330161757484

2. 遊戲玩法2

請編寫一個 SQL 查詢,描述每一個玩家首次登陸的裝置名稱

查詢結果格式在以下示例中:

Activity table:
+-----------+-----------+------------+--------------+
| player_id | device_id | event_date | games_played |
+-----------+-----------+------------+--------------+
| 1         | 2         | 2016-03-01 | 5            |
| 1         | 2         | 2016-05-02 | 6            |
| 2         | 3         | 2017-06-25 | 1            |
| 3         | 1         | 2016-03-02 | 0            |
| 3         | 4         | 2018-07-03 | 5            |
+-----------+-----------+------------+--------------+

Result table:
+-----------+-----------+
| player_id | device_id |
+-----------+-----------+
| 1         | 2         |
| 2         | 3         |
| 3         | 1         |
+-----------+-----------+
  • 跟1基本一樣,只不過這回的輸出位device_id
with t as (
    select player_id, device_id, rank() over (PARTITION BY player_id ORDER BY event_date) as rk from activity
)
select player_id, device_id from t
where rk = 1;

image-20210330162152176

3. 遊戲玩法3

編寫一個 SQL 查詢,同時報告每組玩家和日期,以及玩家到目前為止玩了多少遊戲。也就是說,在此日期之前玩家所玩的遊戲總數。詳細情況請檢視示例。

查詢結果格式如下所示:

Activity table:
+-----------+-----------+------------+--------------+
| player_id | device_id | event_date | games_played |
+-----------+-----------+------------+--------------+
| 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            |
+-----------+-----------+------------+--------------+

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 個遊戲。
請注意,對於每個玩家,我們只關心玩家的登入日期。
  • 通過視窗函式sum實現疊加
select player_id,
       event_date,
       sum(games_played) over (PARTITION BY player_id ORDER BY event_date) as games_played_so_far
from activity

image-20210330163434328

4. 遊戲玩法4

編寫一個 SQL 查詢,報告在首次登入的第二天再次登入的玩家的比率,四捨五入到小數點後兩位。換句話說,您需要計算從首次登入日期開始至少連續兩天登入的玩家的數量,然後除以玩家總數。

查詢結果格式如下所示:

Activity table:
+-----------+-----------+------------+--------------+
| player_id | device_id | event_date | games_played |
+-----------+-----------+------------+--------------+
| 1         | 2         | 2016-03-01 | 5            |
| 1         | 2         | 2016-03-02 | 6            |
| 2         | 3         | 2017-06-25 | 1            |
| 3         | 1         | 2016-03-02 | 0            |
| 3         | 4         | 2018-07-03 | 5            |
+-----------+-----------+------------+--------------+

Result table:
+-----------+
| fraction  |
+-----------+
| 0.33      |
+-----------+
只有 ID 為 1 的玩家在第一天登入後才重新登入,所以答案是 1/3 = 0.33
  • 優先rank排序
  • 然後通過first_value獲取最早日期寫到表中
  • 然後通過比較rank為2的event_date和最早日期,如果 event_date - date2 = 1,那麼符合條件
  • 然後將數值除以rank為1的數量,也就是人數
with t as (
    select player_id, event_date, rank()over(PARTITION BY player_id ORDER BY event_date) as rk from activity
),
t2 as (
    select player_id, event_date, rk, first_value(event_date)over(PARTITION BY player_id) as date2 from t where rk <= 2
)
select round((select count(1) from t2 where event_date - date2 = 1)/(select count(1) from t2 where rk = 1), 2) as fraction

image-20210330171426358

5. 遊戲玩法5

玩家的 安裝日期 定義為該玩家的第一個登入日。

玩家的 第一天留存率 定義為:假定安裝日期為 X 的玩家的數量為 N ,其中在 X 之後的某一天重新登入的玩家數量為 M ,M/N 就是第一天留存率,四捨五入到小數點後兩位。

編寫一個 SQL 查詢,報告所有安裝日期、當天安裝遊戲的玩家數量和玩家的第一天留存率。

查詢結果格式如下所示:

Activity 表:
+-----------+-----------+------------+--------------+
| player_id | device_id | event_date | games_played |
+-----------+-----------+------------+--------------+
| 1         | 2         | 2016-03-01 | 5            |
| 1         | 2         | 2016-03-02 | 6            |
| 2         | 3         | 2017-06-25 | 1            |
| 3         | 1         | 2016-03-01 | 0            |
| 3         | 4         | 2016-07-03 | 5            |
+-----------+-----------+------------+--------------+

Result 表:
+------------+----------+----------------+
| install_dt | installs | Day1_retention |
+------------+----------+----------------+
| 2016-03-01 | 2        | 0.50           |
| 2017-06-25 | 1        | 0.00           |
+------------+----------+----------------+
玩家 1 和 3 在 2016-03-01 安裝了遊戲,但只有玩家 1 在 2016-03-02 重新登入,所以 2016-03-01 的第一天留存率是 1/2=0.50
玩家 2 在 2017-06-25 安裝了遊戲,但在 2017-06-26 沒有重新登入,因此 2017-06-25 的第一天留存率為 0/1=0.00
  • 根據4的思路可以獲取到留存的情況,根據日期做統計
  • 然後通過rank為1的也就是安裝日期做統計
  • 然後通過日期join獲取安裝日期和留存情況
  • 然後通過獲取比值即可
with t as (
    select player_id, event_date, rank() over (PARTITION BY player_id ORDER BY event_date) as rk from activity
),
     t1 as (
         select player_id, event_date, rk, first_value(event_date) over (PARTITION BY player_id) as date2
         from t
         where rk <= 2
     ),
     t2 as (select date2, count(1) as count from t1 where event_date - date2 = 1 group by date2),
     t3 as (select event_date, count(1) as installs from t where rk = 1 group by event_date),
     t4 as (select t3.event_date as install_dt, t3.installs, t2.count
            from t3
                     left join t2 on t3.event_date = t2.date2)
select install_dt,
       installs,
       ROUND((case when count is null then 0 else count end) / installs, 2) as Day1_retention
from t4

image-20210330192918379