博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
SQL判断分段的连续值
阅读量:5143 次
发布时间:2019-06-13

本文共 3076 字,大约阅读时间需要 10 分钟。

有 时候我们需要找出在一组连续的号码中,有哪些是缺失的部分。具体的需求又分为两种情况

  1. 查找 连续部分的最大和最小值
  2. 查找缺少的部分
经过构造的数据如下
-- preparation drop table test1 purge; create table test1(id int,dt date); insert into test1   (id, dt) select rownum as id, trunc(add_months(sysdate, rownum), 'mm') as dt from dual   connect by rownum <= 20; delete test1 where id in (4,7,13,19); commit; SQL> select * from test1;   ID DT ---- -----------    1 2009-4-1 2 2009-5-1 3 2009-6-1 5 2009-8-1 6 2009-9-1 8 2009-11-1 9 2009-12-1 10 2010-1-1 11 2010-2-1 12 2010-3-1 14 2010-5-1 15 2010-6-1 16 2010-7-1 17 2010-8-1 18 2010-9-1 20 2010-11-1 16 rows selected
查找 连续部分的最大和最小值
下面的场景是连续部分的起始和终点,使用NUMBER类型
-- case 1 number type + rownum select min(v2.id) as n1, max(v2.id) as n2 from (select v1.id, (v1.id - rownum) as delta from (select id from test1 order by id) v1) v2 group by v2.delta order by 1;     首先需要对取出的id值进行排序     用这个id值和rownum相减,如果差值是相同的,说明这些id是连续的         N1         N2 ---------- ----------          1          3 5          6 8         12 14         18 20         20
然后使用分析函数实现 同样的功能。
-- case 2 number type + analyse func with v as (select id,        lag(id) over(order by id) as lag,        lead(id) over(order by id) as lead from test1 order by id) select v1.id, v2.id from (select v.id, rownum as rn from v where (v.id - v.lag) != 1 or v.lag is null) v1,        (select v.id, rownum as rn from v where (v.lead - v.id) != 1 or v.lead is null) v2 where v1.rn = v2.rn;     这里使用WITH构造一个视图,避免了对表的多次扫描     如果一个ID值和它的上一个值之间的绝对值差不是1,表示发生了跳跃。     这个ID是某个连续区间的最小或者最大
相同的需求,不同的是这里使用日期类型。注意,因为构造的数据是以MONTH为单位的,所以这里需要使用months_between()来计算差值。
-- case 3 date type + rownum select min(v2.dt) as n1, max(v2.dt) as n2 from (select v1.dt,                months_between(v1.dt, trunc(add_months(sysdate, rownum), 'mm')) as delta from (select dt from test1 order by id) v1) v2 group by v2.delta order by 1; N1          N2 ----------- ----------- 2009-4-1    2009-6-1 2009-8-1    2009-9-1 2009-11-1   2010-3-1 2010-5-1    2010-9-1 2010-11-1   2010-11-1
查找缺少的部分
查找缺少的部分,基本思路是在找到连续部分的基础上,构造缺少的值
-- case 4 find lost value with v as (select min(v2.id) as n1, max(v2.id) as n2,        lead(min(v2.id)) over(order by min(v2.id)) as n3 from (select v1.id, (v1.id - rownum) as delta from (select id from test1 order by id) v1) v2 group by v2.delta order by 1) select t1.sid + t2.rn as lost from (select v.n2 as sid, v.n3 as eid from v) t1,        (select rownum rn from dual connect by rownum <= 50) t2 where t1.sid + t2.rn < t1.eid;     使用case1的算法得到连续部分的最大n2,最小值n1     使用lead函数把某个最大值n2和下一个最小值n3 放到同一行     使用rownum构造连续的缺少部分       LOST ----------          4 7 13 19
另一种查找缺少的方 法,使用外连接
-- case 5 find lost value with v as (select min(id) as n1, max(id) as n2 from test1) select t2.rn as lost from v, test1 t1, (select rownum rn from dual connect by rownum <= 50) t2 where t2.rn between v.n1 and v.n2 and t1.id(+) = t2.rn and t1.id is null order by t2.rn;     取得表的最大n2和最小n1,这里是全部数据的集合     构造大表,并且只取得最大最小之间的rownum     使用外连接取得缺少的值     注意:和case4相比,这个方法要扫描两次表
Note: 更复杂的情况,可以参考Partition Outter Join

转载于:https://www.cnblogs.com/wait4friend/archive/2012/01/31/2334552.html

你可能感兴趣的文章
找到树中指定id的所有父节点
查看>>
jQuery on(),live(),trigger()
查看>>
treegrid.bootstrap使用说明
查看>>
[Docker]Docker拉取,上传镜像到Harbor仓库
查看>>
javascript 浏览器类型检测
查看>>
记录:Android中StackOverflow的问题
查看>>
导航,头部,CSS基础
查看>>
[草稿]挂载新硬盘
查看>>
[USACO 2017 Feb Gold] Tutorial
查看>>
关于mysql中GROUP_CONCAT函数的使用
查看>>
OD使用教程20 - 调试篇20
查看>>
gzip
查看>>
转负二进制(个人模版)
查看>>
LintCode-Backpack
查看>>
查询数据库锁
查看>>
我对于脚本程序的理解——百度轻应用有感
查看>>
面试时被问到的问题
查看>>
当前记录已被另一个用户锁定
查看>>
Node.js 连接 MySQL
查看>>
那些年,那些书
查看>>