SQL,力扣题目1285,找到连续区间的开始和结束数字【窗口函数】
一、力扣链接
LeetCode_1285
二、题目描述
表:Logs
+---------------+---------+ | Column Name | Type | +---------------+---------+ | log_id | int | +---------------+---------+ id 是上表具有唯一值的列。 上表的每一行包含日志表中的一个 ID。
编写解决方案,得到 Logs
表中的连续区间的开始数字和结束数字。
返回结果表按照 start_id
排序。
三、目标拆解
四、建表语句
Create table If Not Exists Logs (log_id int)
Truncate table Logs
insert into Logs (log_id) values ('1')
insert into Logs (log_id) values ('2')
insert into Logs (log_id) values ('3')
insert into Logs (log_id) values ('7')
insert into Logs (log_id) values ('8')
insert into Logs (log_id) values ('10')
五、过程分析
1、窗口函数的连续问题,使用差值法
2、这里计算排名的最大值也可以使用窗口函数,不过order by 后面的字段为倒序
3、流程控制,排名最小的为起始值,排名最大的为结束值
六、代码实现
with t1 as(
select
log_id,
row_number() over(order by log_id) rn
,log_id - row_number() over(order by log_id) diff -- 不能减成结果为负数
from logs
)
# select * from t1;
,t2 as(
select log_id, diff,
row_number() over(partition by diff order by log_id) rn,
count(1) over(partition by diff) total
from t1
)
# select * from t2;
select max(if(rn = 1, log_id, null)) start_id, -- 使用聚合函数就行
max(if(rn = total, log_id, null)) end_id
from t2
group by diff, total
order by start_id;
七、结果验证
八、小结
1、CTE 表达式 + 排名函数 + 聚合函数 + if 条件判断
2、针对排名后数据,计算差值找到连续数字,根据差值分组给组内成员进行排名,根据差值和组内成员总数分组,排名最小的为起始值,排名最大的为结束值
3、聚合函数max() 计算时会忽略null 值
4、count(1) 用来计算总数,数据量大的情况下效率较高
5、连续区间求差值