Oracle中获取连续的序列号范围的SQL (二)

方案3的思路比较值得学习,我们将层层剖析它的结构:

1:对每一条记录找它的前一行

所谓连续的序列号就是看相同格式的情况下前一行记录与当前行的记录序号的值是否相差为1:

  • 如果相差为1,则说明两个序列号是连续的;
  • 如果不为1,则两个序列号不是连续的

select numFormat,
lag(code, 1) over(partition by numFormat order by code) previousCode, code,
max(code) over(partition by numFormat) maxn
from inventory;

2:过滤掉中间连续序列号。

这里通过比较当前序列号与前一行的序列号相减是非相差为1,相差为1将被过滤掉;相差不为1比如2或者说有null值则不被过滤。

select * from(

select numFormat,
lag(code, 1) over(partition by numFormat order by code) previousCode, code,
max(code) over(partition by numFormat) maxn
from inventory

)
where nvl(code-previousCode-1,1) <> 0
;

3:把当前行的code列作为 startNum,后一行的previouscode列作为endNum

select numFormat,code startNum, lead(previousCode) over(partition BY numFormat order by previousCode ) endNum from(

select numFormat,
lag(code, 1) over(partition by numFormat order by code) previousCode, code,
max(code) over(partition by numFormat) maxn
from inventory

)
where nvl(code-previousCode-1,1) <> 0
;

但是我们这里却得到了错误的结果。

这里面有两个问题:

  • 使用lead函数往后找的过程中,如果当前行已经是最后一行,则应该使用最大数字作为endNum,所以需要使用nvl函数来判断是否为null。
  • 本该是第一行的的记录跑startNum为1的居然放到了最后一行。经过调查,previousCode的值存在为null的情况,oracle通常遇到为null值是把null放在最后,所以我们需要添加previousCode为null的行要排在前面。使用nulls first.

4:修复第3步的问题。

select numFormat,code startNum, nvl(lead(previousCode) over(partition BY numFormat order by previousCode nulls first ),maxn) endNum from(

select numFormat,
lag(code, 1) over(partition by numFormat order by code) previousCode, code,
max(code) over(partition by numFormat) maxn
from inventory

)
where nvl(code-previousCode-1,1) <> 0
;

注意红色部分的修改,这样就可以得到如下正确的结果。

原文地址:https://www.cnblogs.com/pmh905001/p/12244514.html

时间: 2024-08-29 12:38:09

Oracle中获取连续的序列号范围的SQL (二)的相关文章

Oracle中按连续号码分段

需要在oracle中将连续的数字分段 模拟数据: fphm  je 1001  20 1002  30 1003  12 1005  32 1006  33 1007  88 1009  99 1010  11 1011  11 如数据所示,发票号码(fphm)中间有中断,我们需要将其按连续性分段,并汇总其金额(je) sql: select fphm,fphm-rownum,je from test_fp order by fphm 执行此语句后,由于rownum是按顺序排列的,所以连续的号码

Oracle中获取当前时间半小时前的时间

最近项目中有个要根据半个小时前的数据情况判断某一栏位的值,但是一直没想到怎样获取当前时间的半小时前的时间,今天突然想到可以通过sysdate做差来获取,比如sysdate-1这样的,刚开始没有对结果进行细看,以为不可以,后来不经意看了之前的结果发现sysdate-1获得的是当前时间的前一天,也就是说sysdate-n获得的是当前时间n天前的结果,所以就试了sysdate-0.5/24这样就获得了需要的结果.OK大功告成.

Oracle中scott用户下基本表练习SQL语句

--选择部门中30的雇员SELECT * from emp where DEPTNO=30;--列出所有办事员的姓名.部门.编号--采用内连接方式,也就是等值链接,也是最常用的链接SELECT ename,empno,dname from emp e INNER JOINdept d on e.deptno=d.deptno where job='CLERK';--找出佣金高于薪金的雇员select * from emp where comm>sal;--找出佣金高于薪金60%的雇员select

Oracle中的表构造导出到word Sql语句

select * from ( SELECT t1.Table_Name AS "表名称", t3.comments AS "表说明", t1.Column_Name AS "字段名称", t1.Data_Type AS "数据类型", t1.Data_Length AS "长度", t1.NullAble AS "是否为空", t2.Comments AS "字段说明&quo

Sql与oracle中null值的区别

原贴链接请点击: 1 null值的介绍 NULL 是数据库中特有的数据类型,当一条记录的某个列为 NULL ,则表示这个列的值是未知的.是不确定的.既然是未知的,就有无数种的可能性.因此, NULL 并不是一个确定的值. 这是 NULL 的由来.也是 NULL 的基础,所有和 NULL 相关的操作的结果都可以从 NULL 的概念推导出来. 2 oracle中的null值介绍 在不知道具体有什么数据的时候,即未知,可以用NULL, 称它为空,ORACLE中,含有空值的表列长度为零.允许任何一种数据

关于oracle中日期使用

spl> select * from emp         where dates          between         to_date('2007-06-12 10:00:00', 'yyyy-mm-dd hh24:mi:ss')         and         to_date('2007-06-12 10:00:00', 'yyyy-mm-dd hh24:mi:ss') 当省略HH.MI和SS对应的输入参数时,Oracle使用0作为DEFAULT值.如果输入的日期数据忽

【翻译自mos文章】对于oracle 数据库来说,OGG的抽取进程什么时候到database中获取数据?

对于oracle 数据库来说,OGG的抽取进程什么时候到database中获取数据? 参考原文: When GoldenGate Fetches Data From The Database On Extraction For Oracle (Doc ID 1059583.1) 适用于: Oracle GoldenGate - Version 4.0.0 and later Information in this document applies to any platform. 解决方法: 问

Oracle中使用游标获取指定数据表的所有字段名对应的字符串

操作步骤:打开PLSQL Developer后,直接执行下面的语句就可以出来 --Oracle中使用游标获取指定数据表的所有字段名对应的字符串 declare mytablename VARCHAR(255):='STAFFDOC'; --定义要查询的数据表名变量,STAFFDOC为我测试用的数据表名,请修改成您的数据库中的对应数据表名字mystring NVARCHAR2(4000):=''; --定义要输出的字符串变量 cursor mycursor is --定义游标          s

Oracle中ID的自动增加以及获取系统时间的小技巧

引自http://blog.csdn.net/lejuo/article/details/4479065 ID自动增加,就像MS- SQL Server里面创建表格时,给表的主键设置为自动增加一样. 在Oracle里面,通过如下的SQL语句实现:(plsql可以直接在sequence创建) -- Create sequence create sequence MSG_IN_ID_SEQminvalue 1maxvalue 999999999999999999999999999start with