零、需求介绍

现有一张表数据如下:

此表是一张镜像表,policyno列代表一个保单号,state列代表这个保单号在snapdate当天的最后一次状态(state每天可能会变很多次,镜像表只保留snapdate时间点凌晨的最后一次状态),
snapdate代表当天做镜像的时间,现在有个需求,我们想取出来这个保单号连续保持某个状态的起止时间,例如:
保单号sm1保持状态1的起止时间为2021020120210202,然后在20210203时候变成了状态2,又在20210204时候变成了状态3,最终又在2021020520210209时间段保持在状态1,
然后镜像表的程序可能期间出现过问题,在20210210开始到20210215日没有镜像成功,直到20210216日才恢复,20210216~20210219日保单号sm1的状态一直保持为1,
后续还有可能继续变,那么,上面说的保单sm1的几个状态的连续时间,我们想要的结果为:

POLICYNO STATE   START_DATE  END_DATE
sm1     1   20210201    20210202
sm1     2   20210203    20210203
sm1     3   20210204    20210204
sm1     1   20210205    20210209
sm1     1      20210216       20210219
.........................

我这里提供5种写法,可以归结为两大类:
一类:通过使用分析函数或自关联获取数据连续性,构造一个分组字段进行分组求最大最小值。
二类:通过树形层次查询获取连续性,获取起止时间。

一、通过使用lag分析函数获取前后时间,根据当前时间与前后时间的差值进行判断获取时间连续性标志,然后使用sum()over()对连续性标志进行累加,从而生成一个新的临时分组字段,最终根据policyno,state,临时分组字段进行分组取最大最小值

这里为了好理解,每一个处理步骤都单独写出来了,实际使用中可以简写一下:

with t as--求出来每条数据当天的前一天镜像时间(select a.policyno,a.state,a.snapdate,lag(a.snapdate) over(partition by a.policyno, a.state order by a.snapdate) as lag_timfrom zyd.temp_0430 aorder by a.policyno, a.snapdate),
t1 as--判断当天镜像时间和前一天的镜像时间+1是否相等,如果相等就置为0否则置为1,新增临时字段lxzt意为:连续状态标志(select t.*,casewhen t.snapdate = t.lag_tim + 1 then0else1end as lxztfrom torder by policyno, snapdate),
t2 as--根据lxzt字段进行sum()over()求和,求出来一个新的用来做分组依据的字段,简称fzyj(select t1.*, sum(lxzt) over(order by policyno, snapdate) as fzyj from t1)
select policyno,--最后根据policyno,state,fzyj进行分组求最大最小值即为状态连续的开始结束时间state,-- fzyj,min(snapdate) as start_snap,max(snapdate) as end_snapfrom t2group by policyno, state, fzyjorder by fzyj;

二、不使用lag分析函数,通过自关联也能判断出来哪些天连续,然后后面操作步骤同上,这个写法算是对lag()over()函数的一个回写,摆脱对分析函数的依赖

下面这种写法,需要读两次表,上面lag的方式是对这个写法的一种优化:

with t as(select a.policyno, a.state, a.snapdate, b.snapdate as snap2from zyd.temp_0430 a, zyd.temp_0430 bwhere a.policyno = b.policyno(+)and a.state = b.state(+)and a.snapdate - 1 = b.snapdate(+)order by policyno, snapdate),
t1 as(select t.*,casewhen snap2 is null then1else0end as lxztfrom torder by policyno, snapdate),
t2 as(select t1.*, sum(lxzt) over(order by policyno, snapdate) as fzyjfrom t1order by policyno, snapdate)
select policyno,state,fzyj,min(snapdate) as start_snap,max(snapdate) as end_snapfrom t2group by policyno, state, fzyjorder by fzyj;

三、通过构造树形结构,确定根节点和叶子节点来获取状态连续的开始和结束时间

先按照数据的连续性构造显示每层关系的树状结构:

with t as(select a.policyno,a.state,a.snapdate,lag(a.snapdate) over(partition by a.policyno, a.state order by a.snapdate) as lag_timfrom zyd.temp_0430 a --where policyno='sm1'order by a.policyno, a.snapdate),
t1 as(select t.*,casewhen t.snapdate = t.lag_tim + 1 then0else1end as lxztfrom torder by policyno, snapdate),
t2 as(select t1.*,lpad('->', (level - 1) * 2, '->') || snapdate as 树状结构,level as 树中层次,decode(level, 1, 1) 是否根节点,decode(connect_by_isleaf, 1, 1) 是否叶子节点,casewhen (connect_by_isleaf = 0 and level > 1) then1end  是否树杈,(prior snapdate) as 根值,connect_by_root snapdate 主根值from t1start with (lxzt = 1)connect by (prior snapdate = snapdate - 1 and prior state = state andprior policyno = policyno)order by policyno, snapdate)
select * from t2;


从上面能清晰的看出来,每一次连续状态的开始日期作为每个树的根,分支节点即树杈和叶子节点的关系一步步拓展开来,分析上面数据我们能够知道,如果我们想要获取
每个保单状态连续时间范围,以上面的数据现有分布方式,现在就可以:通过policyno,state,主根值进行group by 取snapdate的最大最小值,类似前面两个写法的最终步骤;
接下来,我们这个第三种写法就是按照这个方式写:

with t as(select a.policyno,a.state,a.snapdate,lag(a.snapdate) over(partition by a.policyno, a.state order by a.snapdate) as lag_timfrom zyd.temp_0430 a --where policyno='sm1'order by a.policyno, a.snapdate),
t1 as(select t.*,casewhen t.snapdate = t.lag_tim + 1 then0else1end as lxztfrom torder by policyno, snapdate),
t2 as(select t1.*,lpad('->', (level - 1) * 2, '->') || snapdate as 树状结构,level as 树中层次,decode(level, 1, 1) 是否根节点,decode(connect_by_isleaf, 1, 1) 是否叶子节点,casewhen (connect_by_isleaf = 0 and level > 1) then1end  是否树杈,(prior snapdate) as 根值,connect_by_root snapdate 主根值from t1start with (lxzt = 1)connect by (prior snapdate = snapdate - 1 and prior state = state andprior policyno = policyno)order by policyno, snapdate)
select policyno,state,min(snapdate) as start_date,max(snapdate) as end_datefrom t2group by policyno, state, 主根值order by policyno, state;

四、参照过程三,既然已经获取了每条数据的主根值和叶子节点的值,这就代表了我们知道了每个保单状态的连续开始和结束时间,那直接取出来叶子节点数据,叶子节点主根值就是开始日期,叶子节点的值就是结束日期,这样我们就不需再group by了

with t as(select a.policyno,a.state,a.snapdate,lag(a.snapdate) over(partition by a.policyno, a.state order by a.snapdate) as lag_timfrom zyd.temp_0430 a --where policyno='sm1'order by a.policyno, a.snapdate),
t1 as(select t.*,casewhen t.snapdate = t.lag_tim + 1 then0else1end as lxztfrom torder by policyno, snapdate),
t2 as(select t1.*,lpad('->', (level - 1) * 2, '->') || snapdate as 树状结构,level as 树中层次,decode(level, 1, 1) 是否根节点,decode(connect_by_isleaf, 1, 1) 是否叶子节点,casewhen (connect_by_isleaf = 0 and level > 1) then1end 是否树杈,(prior snapdate) as 根值,connect_by_root snapdate 主根值from t1start with (lxzt = 1)connect by (prior snapdate = snapdate - 1 and prior state = state andprior policyno = policyno)order by policyno, snapdate)
select policyno, state, 主根值 as start_date, snapdate as end_datefrom t2where 是否叶子节点 = 1order by policyno, snapdate

五、在Oracle10g之前,上面树状查询的关键函数 connect_by_root还不支持,如果使用树形结构,可以通过sys_connect_by_path来实现

with t as(select a.policyno,a.state,a.snapdate,lag(a.snapdate) over(partition by a.policyno, a.state order by a.snapdate) as lag_tim--case when lag(a.snapdate) over(partition by a.policyno, a.state order by a.snapdate) is null then snapdate else lag(a.snapdate) over(partition by a.policyno, a.state order by a.snapdate) end as lag_timfrom zyd.temp_0430 aorder by a.policyno, a.snapdate),
t1 as(select t.*,casewhen t.snapdate = t.lag_tim + 1 then0else1end as lxztfrom torder by policyno, snapdate),
t2 as(select t1.*,sys_connect_by_path(snapdate, ',') as pt,level,connect_by_isleaf as cbfrom t1start with (lxzt = 1)connect by (prior snapdate = snapdate - 1 and prior state = state andprior policyno = policyno))
select t2.*,regexp_substr(pt, '[^,]+', 1, 1) as start_date,regexp_substr(pt, '[^,]+', 1, regexp_count(pt, ',')) as end_datefrom t2where cb = 1order by policyno, state;


还有好多其他写法,这里不再一一列举,有兴趣的可以评论下面写出其他方案奥!

Oracle数仓中判断时间连续性的几种SQL写法相关推荐

  1. Oracle数仓分区表创建及其数据清理存储过程

    Oracle数仓中,由于客户要求不能有delete语句,delete语句会对每一条数据记录一条日志,造成很慢,日志太大的问题.同时由于传统数仓容量限制,需要对历史数据进行一个归档,归档之后需要对历史数 ...

  2. Apache Doris在美团外卖数仓中的应用实践

    来自:美团技术团队 美团外卖数据仓库通过MOLAP+ROLAP双引擎模式来适配不同应用场景.MOLAP引擎使用了Apache Kylin.ROLAP我们经过综合考虑,选择了Apache Doris.本 ...

  3. Hive 数仓中常见的日期转换操作

    (1)Hive 数仓中一些常用的dt与日期的转换操作 下面总结了自己工作中经常用到的一些日期转换,这类日期转换经常用于报表的时间粒度和统计周期的控制中 日期变换: (1)dt转日期 to_date(f ...

  4. 数仓中指标-标签,维度-度量,自然键-代理键,数据集市等各名词解析及关系

    序列号 内容 链接 1 大数据知识面试题-通用(2022版) https://blog.csdn.net/qq_43061290/article/details/124819089 2 大数据知识面试 ...

  5. 数仓中应该出现的所有表格

    数仓中应该出现的所有表格及其逻辑 1.ods_app_log(app日志贴源表) 计算:详情请见数据预处理整体代码实现 源表:原始数据 +--------------+---------------- ...

  6. 数仓中指标-标签,维度-度量,自然键-代理键等各名词深度解析

    作为一个数据人,是不是经常被各种名词围绕,是不是对其中很多概念认知模糊.有些词虽然只有一字之差,但是它们意思完全不同,今天我们就来了解下数仓建设及数据分析时常见的一些概念含义及它们之间的关系. 本文首 ...

  7. 数仓中的口径及常用口径

    最近去面试,被面试官问到,你们的数仓搭建过程中的口径是什么?当时一脸懵逼,不知道如何回答,这是什么鬼?后来阅读了几篇博文,哦~~~原来口径指的就是你的取数逻辑,也就是你们的一套规则,口径是统计学中的一 ...

  8. 数仓中关于“维度” “粒度”的详细理解(转)

    一.维度是什么 不懂就问,维度是什么?我们学习的自然反应,自然是去查阅专业资料. 1)阿里dataphin产品简介--基本概念是这样介绍维度:人们观察事物的角度,是指一种视角,是确定事物的多方位.多角 ...

  9. Java 中验证时间格式的 4 种方法

    大家好,今天咱们来讲一下,Java 中如何检查一个字符串是否是合法的日期格式? 为什么要检查时间格式? 后端接口在接收数据的时候,都需要进行检查.检查全部通过后,才能够执行业务逻辑.对于时间格式,我们 ...

最新文章

  1. ubuntu 14.04 安装 vmware 10 X64 后无法启动解决方法
  2. websocket中发生数据丢失_为什么事实上却发生了数据丢失,只有少部 分数据可以加载进来...
  3. 升级Firefox8后watir-webdriver出现错误“unable to obtain stable firefox connection in 60 seconds”...
  4. 微信一键关注 php,微信公众平台开发一键关注微信公众平台账号
  5. 【前端学习日记】用reveal.js实现制作网页幻灯片
  6. leetcode100. 相同的树(dfs)
  7. 抢先看!Kubernetes v1.21 新特性一览
  8. ECCV 2020 论文大盘点—显著目标检测篇
  9. 决策树系列(一)——基础知识回顾与总结
  10. unity游戏模型获取- AssertStudio(原GuiStudio)(以第二银河为例)
  11. java 使用xml生成word_java 根据word xml模板生成word
  12. B站笔试真题之[编程题]扭蛋机
  13. EasyCVR搭建视频安防综合运维管理平台,联合集成商打造专业视频解决方案
  14. Android关机闹钟实现
  15. 三天流量有效期具体怎么算_飞猪流量有效期多久?怎么提取?
  16. 关于DBeaver连接mysql驱动下载失败问题【数据库】
  17. 计算机怎么查询隐藏的字体,Win10怎么隐藏不使用的字体?隐藏字体的方法
  18. 阿里、B站都是新股东,康佳旗下易平方有望成为A股首家OTT公司?
  19. 【阅读】A Comprehensive Survey on Distributed Training of Graph Neural Networks——翻译
  20. Microsoft Excel 出现错误。很抱歉,您的Office安装无法正常工作,请使用控制面板中的“程序与功能”选项修复您的产品。您也可以联机查找更多帮助。

热门文章

  1. 博客发在win10.me
  2. java中random方法取值范围_java的Random类详解
  3. 游戏公司logo设计-游戏公司品牌设计-兴动设计
  4. arcgis xml 下载 切片_生成切片缓存切片方案
  5. 传授无知女票IT技能系列——批量删除excel数据前后的空格
  6. 数字金融面板数据:金融效率、数字金融指数、不变价GDP、经济开放度
  7. python数据分析基础试卷及答案_PYTHON数据分析基础_章节测验,期末考试,慕课答案查询公众号...
  8. 锦城学院计算机系考研,锦城学院为2020考研学子加油
  9. 一级计算机网络应用题目操作,计算机一级有什么用 主要考什么
  10. ubuntu10.04正式版下载地址