leetcode数据库(一)

数据库

第一篇


leetcode数据库大全

  • 数据库
    • leetcode511 Game Play Analysis I 游戏玩家分析I找出每个玩家第一次登录的日期
    • leetcode512 Game Play Analysis II 游戏玩家分析II reports the device that is first logged in for each player
    • leetcode534 游戏玩家分析III 玩家在日期A之前玩游戏的个数


leetcode511 Game Play Analysis I 游戏玩家分析I找出每个玩家第一次登录的日期

Table: Activity

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

(player_id, event_date) is the primary key of this table.
This table shows the activity of players of some game.
Each row is a record of a player who logged in and played a number of games (possibly 0) before logging out on some day using some device.

Write an SQL query that reports the first login date for each player.

The query result format is in the following example:

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 | first_login |
+-----------+-------------+
| 1         | 2016-03-01  |
| 2         | 2017-06-25  |
| 3         | 2016-03-02  |
+-----------+-------------+

找出每个玩家第一次登录的日期。
按玩家分组,求每个玩家登录日期的最小值。

select player_id,min(event_date) as `first_login`
from Activity
group by player_id

leetcode512 Game Play Analysis II 游戏玩家分析II reports the device that is first logged in for each player

Table: Activity

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

(player_id, event_date) is the primary key of this table.
This table shows the activity of players of some game.
Each row is a record of a player who logged in and played a number of games (possibly 0) before logging out on some day using some device.

Write a SQL query that reports the device that is first logged in for each player.

The query result format is in the following example:

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         |
+-----------+-----------+
select A.player_id,A.device_id
from Activity as A
where A.event_date = (
    select event_date
    from Activity
    where player_id = A.player_id
    order by event_date
    limit 0,1
)
 
select A.player_id,A.device_id
from 
Activity as A
join
(
    select player_id,min(event_date) as `mdate`
    from Activity
    group by player_id
) as B
on(A.player_id = B.player_id and A.event_date = B.mdate)
select A.player_id,A.device_id
from Activity as A
where (A.player_id,A.event_date) in
(
    select player_id,min(event_date) as `mdate`
    from Activity
    group by player_id
)

解法一

对每个玩家,判断其是不是玩家登录的最早时间。登录的最早时间通过子查询判断。
select A.player_id,A.device_id
from Activity as A
where A.event_date = (
    select event_date
    from Activity
    where player_id = A.player_id
    order by event_date
    limit 0,1
)

解法二

对玩家分组,找出每个玩家的最早登录日期。
(
    select player_id,min(event_date) as `mdate`
    from Activity
    group by player_id
) as B
再连接Activity表,筛选出每个玩家,最早登录日期时的设备。
select A.player_id,A.device_id
from 
Activity as A
join
(
    select player_id,min(event_date) as `mdate`
    from Activity
    group by player_id
) as B
    on(A.player_id = B.player_id and A.event_date = B.mdate)
不用连接,用in也行的。
select A.player_id,A.device_id
from 
Activity as A
where (A.player_id,A.event_date) in
(
    select player_id,min(event_date) as `mdate`
    from Activity
    group by player_id
)

leetcode534 游戏玩家分析III 玩家在日期A之前玩游戏的个数

Table: Activity

±-------------±--------+
| Column Name | Type |
±-------------±--------+
| player_id | int |
| device_id | int |
| event_date | date |
| games_played | int |
±-------------±--------+
(player_id, event_date) is the primary key of this table.
This table shows the activity of players of some game.
Each row is a record of a player who logged in and played a number of games (possibly 0) before logging out on some day using some device.

Write an SQL query that reports for each player and date, how many games played so far by the player. That is, the total number of games played by the player until that date. Check the example for clarity.

The query result format is in the following example:

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 |
±----------±-----------±--------------------+
For the player with id 1, 5 + 6 = 11 games played by 2016-05-02, and 5 + 6 + 1 = 12 games played by 2017-06-25.
For the player with id 3, 0 + 5 = 5 games played by 2018-07-03.
Note that for each player we only care about the days when the player logged in.

SELECT B.player_id,B.event_date,SUM(A.games_played) AS `games_played_so_far`
FROM Activity AS A 
JOIN Activity AS B 
ON (A.player_id = B.player_id AND A.event_date <= B.event_date)
GROUP BY B.player_id,B.event_date

分析每个玩家在日期A之前玩游戏的个数。
解法一

先按player_id和event_date升序,再统计每个人的玩游戏的前缀和。
对于前缀和,用户变量解决更合适。
用户变量:pre_id——上一行的player_id,pre_date—— 上一行的event_date,sum_cnt——每个人games_played前缀和。
(SELECT @pre_id:=NULL,@pre_date:=NULL,@sum_cnt:=0) AS B
前缀和计算逻辑:
if (当前行的player_id = pre_id and 当前行的event_date != pre_date){
    sum_cnt = sum_cnt + 当前行的games_played
}else{
    sum_cnt = games_played
}
连接表Activity和表B:
SELECT 
	A.player_id,
	A.event_date,
@sum_cnt:= IF(A.player_id = @pre_id AND A.event_date != @pre_date,
			@sum_cnt + A.games_played,
			A.games_played 
		) AS `games_played_so_far`,
@pre_id:=A.player_id AS `player_ids`,
@pre_date:=A.event_date AS `event_dates`
FROM 
activity AS A,(
SELECT @pre_id:= NULL,@pre_date:= NULL,@sum_cnt:=0) AS B
ORDER BY A.player_id,A.event_date
但由于用户变量的限制,多出了两个字段player_ids,event_dates。
再投一次影,去掉多出的字段。
SELECT C.player_id,C.event_date,C.games_played_so_far
FROM (
SELECT 
	A.player_id,
	A.event_date,
@sum_cnt:=
		if(A.player_id = @pre_id AND A.event_date != @pre_date,
			@sum_cnt + A.games_played,
			A.games_played 
		)
		AS `games_played_so_far`,
@pre_id:=A.player_id AS `player_ids`,
@pre_date:=A.event_date AS `event_dates`

FROM 
activity AS A,(SELECT @pre_id:=NULL,@pre_date:=NULL,@sum_cnt:=0) AS B
order BY A.player_id,A.event_date
) AS C

解法二
将每个人,在日期A当天和之前,玩过的游戏个数累加。
同一个,在日期A当天和之前,用表自连接,group by,找出这些行。也是这类累加和或前缀和问题的通用解法。

SELECT *
FROM Activity AS A JOIN Activity AS B ON (A.player_id = B.player_id AND A.event_date <= B.event_date)
补上group by及组内求和。
SELECT B.player_id,B.event_date,SUM(A.games_played) AS `games_played_so_far`
FROM Activity AS A JOIN Activity AS B 
ON (A.player_id = B.player_id AND A.event_date <= B.event_date)
GROUP BY B.player_id,B.event_date

你可能感兴趣的:(#,sql,数据库,leetcode)