Oracle连续日期怎么拼接?

 九月份复习,十月份考试,十月底一直没法收心,赶在十一初 由于不可抗拒的原因又不得不重新找工作就;欸~,
又是一番折腾,从入职到现在,可又没法闲下来了...

这次就简单介绍下oracle数据库下如何实现行转列、列转行及此在mybatis中的实现方式,就具体用法我就不详细说了,主要介绍下实战中所碰到的坑~

行转列大致的实现方式大致有三种

 这种方式sql难度低,但是容易给DB造成较大的开销,毕竟每个最终的列的值都是一个聚合函数的值,同时非聚合列也要随聚合列而定,大多数情况下可能需要将多个子查询连表查;至于在mybatis中的时候就非常简单了,这里就不再缀诉哈~
  • 使用pivot函数方式

 此种方式有一个缺点是:一次查询只能对一个列的数据进行拆分(成多列),如需对多列拆分,则可行的方式是做多个查询,一个查询拆分一列(同时保留连接字段),
同时,这里需要主要的是 在 pivot 下的in中不可以是一个子查询,记得当时调试的时候怎么调试就是报错,后来翻了翻英文网站的说明,给的大致意思是这个pivot内拆分的目标字段不可以是一个子查询,只能是写死的列 ,其实也不是不可以,只是官方给出的说法是:要实现动态列,只能使用xml的方式(说了等于没说)。
 ok,待SQL调试完毕,copy到应用中使用的时候还是会报错,这个时候就需要注意到mybatis的一些基本约定,就是传值方式,mybatis的传值方式大致有#{value}和${value}两种方式
,#符号定义的值其实是将整个值对象交给DBMS去处理,而$符号定义的值是将值直接放入到语句内,对DBMS来说,后者更相当于一个定值,所以将povit应用在mybatis中需要使用$的值定义方式(仅在in内这样使用,pivot外视业务情况而定)。
 同时,因为使用$符号定义值的方式不时mybatis并不会将传入的值作为一个String字符来处理,如果是日期及其他类型尽量使用string的方式将值传入,拆分的值若是日期类型的需要
使用to_date()函数或者_to_char()_函数进转换才是,如果目标值就是String类型且一定要将整个声明值使用单引号引起来('#{value}'),另外,拆分的目标列也是可以定义别名的,不然DB
 
 
 这种方式其实很容易将sql写的很复杂,主要有两个方面:一个是wm_concat 函数一定要指定partition by和order by的字段,就是组内分组和组内排序方式,不然最终的结果数据混乱不堪(除非这对你的业务不重要),另一个原因是窗口函数本身是不会聚合行,所以,组内拼接也是顺序拼接,所以需要做的就是将非结果行去掉才是,这个时候就需要使用另一个窗口函数rank(),这个函数是对组内做排序,由于目标是实现行转列,所以此时就需要将rank()的排序方式改为desc,而后再做一个子查询将rank的值为非1的全去掉。
 由于使用wm_concat的结果是单列,需要此时需要根据逗号做分隔,截取为指定的列,wm_concat函数使用起来并不难,但是面对实际业务的时候,若是大数据量就得慎重咯,因为函数使用的越多就越容易造成DB的开销,这个是不容忽视的。 wm_concat在mybatis中的使用并没有障碍,需要注意的细节是拼接字段可能不是varchar类型,而是blob(大字段)类型,需要用to_char()函数做转换,同时wm_concat函数只能按照逗号进行内容拼接,如果字符包含逗号,建议将wm_concat内的源字段拼接一个唯一字符。
 
 
 
 此种方式同以上的pivot的方式相反,不过好处是他不会有行转列的单列问题,至于在mybatis中的使用,建议参照以上pivot的方式
 
 
 其实这个函数的说的意义并不大,因为regexp_substr函数在拆分十行数据的时候DB的开销就显现出来了,如果不得已要用的话首先推荐使用程序来处理,如果使用数据库处理,建议将
目标数据拆分多个组来做,建议不要超过十个,而且拆分的列的数据复杂度不能太高(字符太长,正则太复杂),在mybatis下的使用中只需要注意下目标列的类型,必要时使用to_char函数进行转换才是~
 
 
 
 相信大家已经猜出一部分了,这里简要说下这三个东东大概是干什么:level实现级的序号增加,connect by 实现递归,rownum则配合运算结果加减,以下就给出具体的SQL,可
 
貌似不使用rownum也是可以的,各位可以尝试下哈~
 
#### 最后,原本在写博客前在个人电脑中跑一个oracle的,实际安装的过程中发现oracle的安装包实在是太大了,许久不安装,安装过程难免也会出现各种问题,遂~就放弃了,改天我会尽量将语句都放出来,以飨广大读者哈~,至于行转列列转行的实现方式就给个粗糙的sql大家尝试着看哈~~
 
}

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

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

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

0

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

0

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

0


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


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

}

我要回帖

更多关于 表格的日期怎么换成连续日期 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信