- 学习:知识的初次邂逅
- 复习:知识的温故知新
- 练习:知识的实践应用
目录
一,原题力扣链接
二,题干
表:
Matches
+-------------+------+ | Column Name | Type | +-------------+------+ | player_id | int | | match_day | date | | result | enum | +-------------+------+ (player_id, match_day) 是该表的主键(具有唯一值的列的组合)。 每一行包括了:参赛选手 id、 比赛时间、 比赛结果。 比赛结果(result)的枚举类型为 ('Win', 'Draw', 'Lose')。选手的 连胜数 是指连续获胜的次数,且没有被平局或输球中断。
编写解决方案来计算每个参赛选手最多的连胜数。
结果可以以 任何顺序 返回。
结果格式如下例所示:
示例 1:
输入: Matches 表: +-----------+------------+--------+ | player_id | match_day | result | +-----------+------------+--------+ | 1 | 2022-01-17 | Win | | 1 | 2022-01-18 | Win | | 1 | 2022-01-25 | Win | | 1 | 2022-01-31 | Draw | | 1 | 2022-02-08 | Win | | 2 | 2022-02-06 | Lose | | 2 | 2022-02-08 | Lose | | 3 | 2022-03-30 | Win | +-----------+------------+--------+ 输出: +-----------+----------------+ | player_id | longest_streak | +-----------+----------------+ | 1 | 3 | | 2 | 0 | | 3 | 1 | +-----------+----------------+ 解释: Player 1: 从 2022-01-17 到 2022-01-25, player 1连续赢了三场比赛。 2022-01-31, player 1 平局. 2022-02-08, player 1 赢了一场比赛。 最多连胜了三场比赛。 Player 2: 从 2022-02-06 到 2022-02-08, player 2 输了两场比赛。 最多连赢了0场比赛。 Player 3: 2022-03-30, player 3 赢了一场比赛。 最多连赢了一场比赛。
三,建表语句
Create table If Not Exists Matches (player_id int, match_day date, result ENUM('Win', 'Draw', 'Lose'))
Truncate table Matches
insert into Matches (player_id, match_day, result) values ('1', '2022-01-17', 'Win')
insert into Matches (player_id, match_day, result) values ('1', '2022-01-18', 'Win')
insert into Matches (player_id, match_day, result) values ('1', '2022-01-25', 'Win')
insert into Matches (player_id, match_day, result) values ('1', '2022-01-31', 'Draw')
insert into Matches (player_id, match_day, result) values ('1', '2022-02-08', 'Win')
insert into Matches (player_id, match_day, result) values ('2', '2022-02-06', 'Lose')
insert into Matches (player_id, match_day, result) values ('2', '2022-02-08', 'Lose')
insert into Matches (player_id, match_day, result) values ('3', '2022-03-30', 'Win')
四,分析
思路
表格分析大法 用啥解答不重要 重要的还是思路和逻辑 表格中把思路和逻辑盘顺, sql或者pandas自然顺手敲来
mysql和pandas完整代码 在最后 不过代码其实不重要,重要的是学会其中的逻辑 和总结规律(方法论);
下次遇到这种题就可以很快解答了
第一步 :开2个排序 分别以player_id分组排序 和游戏id,比赛成绩排序 生成2个序列
第二步:求差值 如果差值相等 则为连续
第三步:以游玩id和差值 分组 聚合胜利的次数 如果是胜利的 if给他1 其余的给0 这样sum就可以拿到连胜次数
第四步:分组求top1呗 每个参赛选手最多的连胜数。
第五步:最后按照题目要求排序
其实汇合起来就是2个步骤 详情见 下方图解
- 第一步 分别分组排序取差值
- 第二步 分组求top1
五,SQL解答
with t1 as (
select player_id, match_day, result,
row_number() over (partition by player_id order by match_day) ro1, -- 以id分组,以日期排序 拿到序列
row_number() over (partition by player_id,result order by match_day) ro2 -- 以id和结果分组 拿到行的序列
from Matches
)
# select * from t1;
, t2 as (
select player_id, match_day, result, ro1, ro2,
ro1-ro2 as diff -- 拿到差值
from t1
)
# select * from t2;
,t3 as (
select player_id,diff,sum(if((result='Win'),1,0)) as sum_res from t2 group by player_id,diff
)
# select * from t3;
select player_id,max(sum_res) as longest_streak from t3 group by player_id;
六,验证
七,知识点总结
- 连续问题 求差值 屡试不爽~~~
- 窗口函数的运用
- 以不同的维度分组排序 得到不同的结果
- 条件过滤的运用 妙用sum 统计次数
- 分组求top1的运用
- 学习:知识的初次邂逅
- 复习:知识的温故知新
- 练习:知识的实践应用