oracle lead/lag 函数 ignore nulls 功能在11g以下版本的实现

oracle在11g中允许对lead/lag分析函数使用ignore nulls 语法以排除空值。这是一个很实用的语法,然而在低版本中却不能使用。本文将介绍几种可以在较低版本中实现类似功能的sql写法。

建立测试表
create table nayi_test_180515 as
select level ord, decode(level, 5, null, 6, null, level) num
  from dual
connect by level <= 8;

select*from nayi_test_180515;
ORDNUM
11
22
33
44
5
6
77
88

对测试数据做了简化。其中ORD列视为按指定排序后获得的递增的唯一序列,NUM列视为数据列。

11g中的写法
select t1.ord, t1.num, 
       lag(t1.num) over(order by t1.ord) lag_,
       lag(t1.num) ignore nulls over(order by t1.ord) lag_ignore_,
       lead(t1.num) over(order by t1.ord) lead_,
       lead(t1.num ignore nulls) over(order by t1.ord) lead_ignore_
  from nayi_test_180515 t1
 order by t1.ord;
ORDNUMLAG_LAG_IGNORE_LEAD_LEAD_IGNORE_
1122
221133
332244
44337
5447
6477
77488
8877
model写法
select*from nayi_test_180515 t1
model
dimension by(row_number() over(order by t1.ord) rn)
measures(ord, num, num lag_, num lag_ignore_, num lead_, num lead_ignore_)
rules(
lag_[rn] = num[cv() - 1],
lag_ignore_[rn] = nvl(num[cv() - 1], lag_ignore_[cv() - 1]),
lead_[rn] = num[cv() + 1],
lead_ignore_[rn] order by rn desc = nvl(num[cv() + 1], lead_ignore_[cv() + 1])
)
;
RNORDNUMLAG_LAG_IGNORE_LEAD_LEAD_IGNORE_
11122
2221133
3332244
444337
55447
66477
777488
88877
使用first_value/last_value+ignore的方法
select t1.*, 
       first_value(t1.num) over(order by t1.ord rows between 1 following and unbounded following) first_lead,
       first_value(t1.num ignore nulls) over(order by t1.ord rows between 1 following and unbounded following) first_ignore,
       last_value(t1.num) over(order by t1.ord rows between unbounded preceding and 1 preceding) last_lag,
       last_value(t1.num ignore nulls) over(order by t1.ord rows between unbounded preceding and 1 preceding) last_ignore
  from nayi_test_180515 t1
 order by ord
;
ORDNUMFIRST_LEADFIRST_IGNORELAST_LAGLAST_IGNORE
1122
223311
334422
44733
5744
6774
77884
8877
自连接
select t1.ord, t1.num, t3.num lag_ignore_
  from nayi_test_180515 t1,
       (select t1.ord, max(t2.ord) t2_ord
          from (select * from nayi_test_180515 t1) t1,
               (select * from nayi_test_180515 t2 where t2.num is not null) t2
         where 1 = 1
           and t1.ord > t2.ord
         group by t1.ord) t2,
       nayi_test_180515 t3
 where 1 = 1
   and t1.ord = t2.ord(+)
   and t2.t2_ord = t3.ord(+)
 order by t1.ord;
ORDNUMLAG_IGNORE_
11
221
332
443
54
64
774
887

因为实现起来过于复杂并且效率非常低,只实现了lag ignore nulls

其他

方法肯定不只这些,欢迎交流。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值