SQL刷题记录——EASY模式1!!

98 阅读1分钟

考点一 聚合函数 + group by

select player_id, min(event_date) first_login
from activity
group by player_id

考点二 MySQL 8.0 的新特性——窗口函数

MySQL 8.0新特性提供了窗口函数,对于排序问题,常用的有三种窗口函数,以数值4,5,5,6为例:

ROW_NUMBER(): 求行数,结果为1,2,3,4
RANK(): 有间隔的分级,结果为1,2,2,4
DENSE_RANK(): 无间隔的分级,结果为1,2,2,3

使用这些窗口函数时,要用over设定窗口,用法为:

function OVER windowName
WINDOW windowName AS (PARTITION BY a_col ORDER BY b_col)

这两行代码含义为设定一个对a_col分组后对每组的b_col排序的窗口,对这个窗口应用function

在本题中,要找到每位玩家第一次登录的设备id,则需要对玩家id进行分组,每组求ROW_NUMBER,使用ROW_NUMBER而不使用其他窗口函数的原因是ROW_NUMBER结果是不重复的,适合本题的场景。


select player_id, device_id
from (
    select player_id, device_id, ROW_NUMBER() OVER(PARTITION BY player_id ORDER BY event_date) as rn
    from activity) as a
where rn = 1;
496 ms

考点三 子查询

select activity.player_id, activity.device_id from activity, (
	select player_id, min(event_date) as first_login
	from activity group by player_id
) as temp
where activity.player_id = temp.player_id
and activity.event_date = temp.first_login;
589 ms

使用 all 配合 <= 筛选出 a1.player_id = a2.player_id 的 event_date 数据

select player_id, device_id from activity a1 where event_date <= all(
	select a2.event_date from activity a2 where a1.player_id = a2.player_id
);
1539 ms

考点四 左连接

select name, bonus
from Employee left join Bonus
on Employee.EmpId = Bonus.EmpId
where bonus is null or bonus < 1000;

考点五 LIMIT

select customer_number
from orders
group by customer_number
order by count(*) desc
LIMIT 1

考点六 round 和 isfull

将两个数字相除并取整 round 到 2 位小数,以得到想要的通过率。
总请求数,也就是分母,有可能为 0。所以我们需要使用 ifnull函数来处理这种特殊情况。

select
round(
    ifnull(
    (select count(*) from (select distinct requester_id, accepter_id from RequestAccepted) as A)
    /
    (select count(*) from (select distinct sender_id, send_to_id from FriendRequest) as B),
    0)
, 2) as accept_rate;