连续出现的数字[如何完美处理连续特定记录问题?]

720 阅读1分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第14天,连续出现的数字[如何完美处理连续特定记录问题?] - 掘金 (juejin.cn)

前言

对于连续问题,在不采用SQL变量的情况下,就需要巧妙的分组(问题转换),针对特定的字段来排序,当序号id - 排序值rank 相等时,说明两条特定的记录是连续的。

一、连续出现的数字

image.png

image.png

二、三种解法

1、暴力联表

select distinct l1.Num ConsecutiveNums
from Logs l1 join Logs l2 on l1.id + 1 = l2.id and l1.num = l2.num
    join Logs l3 on l2.id + 1 = l3.id and l2.num = l3.num

2、巧妙分组

with view4row as(
    select Id,num,
        # 防止id不连续。
        row_number() over() `row`
    from Logs
),view4rank as(
    select id,num,`row`,
    # 注:rank()等排序会打乱该view的记录顺序。
    rank() over(partition by num order by `row`) rk
    from view4row
)
select distinct Num ConsecutiveNums 
from view4rank
#`row` - rk相等的就代表在num相等的基础上,这些相等的num是连续的,这就是分析中 如何分组问题 的转换。
group by Num,`row` - rk 
having count(1) > 2

3、加入变量

with view4base as(
    select num,
        case
            when num = @pre then @cnt:=@cnt+1
            when true       then @cnt:=1
        end cnt,
        @pre:=num
    from (select num from Logs) t1,(select @cnt:=1,@pre:='') t2 # 笛卡儿积把变量打到每条记录末尾。
)
select distinct Num ConsecutiveNums 
from view4base
where cnt > 2

总结

1)连续问题,就要面向要求的特定字段,以其分组排序,通过序号id - 排序值rank来将连续的分为一组。

2)除了问题转换的巧妙解法,也可以通过笛卡儿积给每行记录打上变量字段,通过操作变量,让SQL更灵活,以达到SQL编程的效果。

参考文献

[1] LeetCode 连续出现的数字