SQL 180. 连续出现的数字

SQL 180. 连续出现的数字

题目 : https://leetcode.cn/problems/consecutive-numbers/

数据

Create table If Not Exists Logs (
  id int, 
  num int
);

Truncate table Logs;

insert into Logs (id, num) values ('1', '1');
insert into Logs (id, num) values ('2', '1');
insert into Logs (id, num) values ('3', '1');
insert into Logs (id, num) values ('4', '2');
insert into Logs (id, num) values ('5', '1');
insert into Logs (id, num) values ('6', '2');
insert into Logs (id, num) values ('7', '2');

需求

查询所有至少连续出现三次的数字

查询结果 :

| ConsecutiveNums |
| 1               |

解决

连续的值 ,有3种情况 ,如:

  • 1, 1, 1, 2, 2, 1, 1 (1 连续性);
  • 1, 2, 1, 1, 2, 1, 1 (都不连续性);
  • 1, 1, 1, 2, 1, 1, 1 (1 连续性, 去重);

方法1

技术点:

  • lead(): 查询当前行向下偏移 n 行的值
  • lag() : 查询当前行向上偏移 n 行的值
lead/lag(列名, 偏移的offset, 超出窗口的默认值) 
	over (partition by 分组列 order by 排序列 
  rows between 开始位置 preceding and 结束位置 following)

查询该行的,下列值,下下列值

select num,
  lead(num, 1, 0) over(order by id) as lead_1,
  lead(num, 2, 0) over(order by id) as lead_2
from Logs

查询结果:

num|lead_1|lead_2|
---+------+------+
  1|     1|     1|
  1|     1|     2|
  1|     2|     1|
  2|     1|     2|
  1|     2|     2|
  2|     2|     0|
  2|     0|     0|

当该行值 = 下列值 = 下下列值就连续相等了

  • 注意点:num可能有相同值多次连续,所以要去重
-- 求下列,下下列
with t1 as (
  select num,
    lead(num, 1, 0) over(order by id) as lead_1,
    lead(num, 2, 0) over(order by id) as lead_2
  from Logs
)
-- 比较下列,下下列,并去重
select num as ConsecutiveNums
from t1
where num = lead_1 and lead_1 = lead_2
group by num;

缺点: 不够通用,当连续 n 次时,就不好处理了

方法2

思路 :

  • 对 num 排序
  • 对 num 进行分区排序
  • 对俩个值进行差值
  • 当差值相同数大于 3 时 , 就说明连续
| num | row_bumber | row_bumber分组 ||
| 1   |       1    |       1        |  0 |
| 1   |       2    |       2        |  0 |
| 1   |       3    |       3        |  0 |
| 2   |       4    |       1        |  3 |
| 2   |       5    |       2        |  3 |
| 1   |       6    |       4        |  2 |
| 1   |       7    |       5        |  2 |

根据id 进行排序 , 避免id不连续情况

select num,
  row_number() over(order by id) as row_bumber
from Logs

查询结果:

num|row_bumber|
---+----------+
  1|         1|
  1|         2|
  1|         3|
  2|         4|
  1|         5|
  2|         6|
  2|         7|

根据 num 分区窗口,在窗口中根据 id 排序

select num,
  row_number() over(partition by num order by id) as row_bumber_partition
from Logs

查询结果:

num|row_bumber_partition|
---+--------------------+
  1|                   1|
  1|                   2|
  1|                   3|
  1|                   4|
  2|                   1|
  2|                   2|
  2|                   3|

对比差值,查看区别

select num,
  row_number() over(order by id) as row_bumber,
  row_number() over(partition by num order by id) as row_bumber_partition,
  row_number() over(order by id) - row_number() over(partition by num order by id) as diff
from Logs

查询结果:

num|row_bumber|row_bumber_partition|diff|
---+----------+--------------------+----+
  1|         1|                   1|   0|
  1|         2|                   2|   0|
  1|         3|                   3|   0|
  2|         4|                   1|   3|
  1|         5|                   4|   1|
  2|         6|                   2|   4|
  2|         7|                   3|   4|

解决 :

-- 求差值
with t1 as(
  select num,
    row_number() over(order by id) - row_number() over(partition by num order by id) as diff
  from Logs
),
-- 筛选连续3次的值
t2 as (
  select num as ConsecutiveNums
  from t1
  group by num, diff
  having count(*) >= 3
)
-- 去重
select num
from t2
group by num;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值