求某表状态变化时,记录下之前之后编号的位置。
本问题由:https://bbs.csdn.net/topics/392280779?page=1#post-411115296 而引发。
现有一个tb_sqsts表,其结构是:
create table tb_sqsts( id number(4,0) not null primary key, seq number(3,0) not null, status number(2,0) not null)
其中填充了这些值:
insert into tb_sqsts(id,seq,status) values('1','1','1'); insert into tb_sqsts(id,seq,status) values('2','3','1'); insert into tb_sqsts(id,seq,status) values('3','7','1'); insert into tb_sqsts(id,seq,status) values('4','5','1'); insert into tb_sqsts(id,seq,status) values('5','4','0'); insert into tb_sqsts(id,seq,status) values('6','9','0'); insert into tb_sqsts(id,seq,status) values('7','16','0'); insert into tb_sqsts(id,seq,status) values('8','12','1'); insert into tb_sqsts(id,seq,status) values('9','10','1'); insert into tb_sqsts(id,seq,status) values('10','6','1'); insert into tb_sqsts(id,seq,status) values('11','2','0'); insert into tb_sqsts(id,seq,status) values('12','22','0');
然后我们查看一下结果:
SQL> select * from tb_sqsts order by seq; ID SEQ STATUS ---------- ---------- ---------- 11 2 0 2 3 1 5 4 0 4 5 1 10 6 1 3 7 1 6 9 0 9 10 1 8 12 1 7 16 0 12 22 0 已选择11行。
现在要求,在status发生变化时,将seq顺序编号记录下来。
期望值就是2-3,3-4,4-5,7-9,9-10,12-16.
需求的难点在于seq并不连续,如果它是连续的,那么seq+1就知道下一条记录,继而知道status值变没变化了。
我们借助oracle的row_number()函数或是rank()函数给这张表添加一个连续的列就好了。
于是有了下面的sql
SQL> select row_number() over (order by seq) as rn,a.* from tb_sqsts a; RN ID SEQ STATUS ---------- ---------- ---------- ---------- 1 11 2 0 2 2 3 1 3 5 4 0 4 4 5 1 5 10 6 1 6 3 7 1 7 6 9 0 8 9 10 1 9 8 12 1 10 7 16 0 11 12 22 0 已选择11行。
然后以新结果集进行自联结,找出那些rn递增而status不同的记录即可:
SQL> select a.seq||'-'||b.seq from 2 (select row_number() over (order by seq) as rn,tb_sqsts.* from tb_sqsts ) a 3 left join (select row_number() over (order by seq) as rn,tb_sqsts.* from tb_sqsts ) b 4 on b.rn=a.rn+1 5 where b.rn is not null 6 and a.status<>b.status; A.SEQ||'-'||B.SEQ --------------------------------------------------------------------------------- 2-3 3-4 4-5 7-9 9-10 12-16 已选择6行。 已用时间: 00: 00: 00.00
从结果看,与期望值一致。
因此,达成需求的最终SQL就是:
select a.seq||'-'||b.seq from (select row_number() over (order by seq) as rn,tb_sqsts.* from tb_sqsts ) a left join (select row_number() over (order by seq) as rn,tb_sqsts.* from tb_sqsts ) b on b.rn=a.rn+1 where b.rn is not null and a.status<>b.status
--2020年3月28日--
上面使用到的全部SQL文:
create table tb_sqsts( id number(4,0) not null primary key, seq number(3,0) not null, status number(2,0) not null) insert into tb_sqsts(id,seq,status) values('1','1','1'); insert into tb_sqsts(id,seq,status) values('2','3','1'); insert into tb_sqsts(id,seq,status) values('3','7','1'); insert into tb_sqsts(id,seq,status) values('4','5','1'); insert into tb_sqsts(id,seq,status) values('5','4','0'); insert into tb_sqsts(id,seq,status) values('6','9','0'); insert into tb_sqsts(id,seq,status) values('7','16','0'); insert into tb_sqsts(id,seq,status) values('8','12','1'); insert into tb_sqsts(id,seq,status) values('9','10','1'); insert into tb_sqsts(id,seq,status) values('10','6','1'); insert into tb_sqsts(id,seq,status) values('11','2','0'); insert into tb_sqsts(id,seq,status) values('12','22','0'); select * from tb_sqsts order by seq select row_number() over (order by seq) as rn,a.* from tb_sqsts a select a.seq||'-'||b.seq from (select row_number() over (order by seq) as rn,tb_sqsts.* from tb_sqsts ) a left join (select row_number() over (order by seq) as rn,tb_sqsts.* from tb_sqsts ) b on b.rn=a.rn+1 where b.rn is not null and a.status<>b.status
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)
2018-03-28 【高中数学/幂函数】y=x^2与y=x^-2 的函数图像