从 SQL 到 SPL:组内按次序将非空值编号

Oracle 库某表按第 1 列、第 2 列排序后,第 3 列有非空值。

CP

ROK

DOPIS_C

6059150790

2014

C

6059150790

2015

C

6059150790

2016

C

6059150790

2017


6059150790

2018

C

6059150790

2019


6059150790

2020

C

6059150790

2021

C

6059150790

2022

C

6059150790

2023


6059150790

2024


6059150791

2014

C

6059150791

2015

C

6059150792

2014


6059150792

2015


6059150792

2016

C

6059150792

2017


6059150792

2018

C

现在要新增计算列 RN_C1:在CP相同的一组数据内,如果 DOPIS_C 有连续的非空值,则从 1 开始按顺序填入编号;如果 DOPIS_C 是空值,则在 RN_C1 填入空值,并从下一个非空值开始重新编号。

CP

ROK

DOPIS_C

RN_C1

6059150790

2014

C

1

6059150790

2015

C

2

6059150790

2016

C

3

6059150790

2017



6059150790

2018

C

1

6059150790

2019



6059150790

2020

C

1

6059150790

2021

C

2

6059150790

2022

C

3

6059150790

2023



6059150790

2024



6059150791

2014

C

1

6059150791

2015

C

2

6059150792

2014



6059150792

2015



6059150792

2016

C

1

6059150792

2017



6059150792

2018

C

1

SQL中用相对位置引用集合成员时要写成繁琐的窗口函数,常常还伴随着嵌套子查询;后面序号计算的逻辑判断也较为复杂,也会有多层case when,代码很臃肿。序号要在指定区间内累计,这要把这些区间拼成某种分组,思路会非常绕。

当然也可以在循环中引用相对位置的集合成员并进行逻辑判断来实现以避开“绕路”,但单句SQL写不出有循环结构,使用存储过程可以实现,但代码仍然繁琐而且架构也复杂了。

SPL支持完整的过程性语法,可以在循环中处理复杂的业务逻辑,还可以方便地用相对位置引用集合成员以简化代码。


 A

1

=orclJDBC.query("select *, null as RN_C1 from tb order by CP,ROK”)

2

=A1.run(RN_C1=if(DOPIS_C ,if(CP==CP[-1],t+=1,t=1),t=null) )

A1:通过JDBC加载数据,按CP,ROK 排序,并新增空计算列RN_C1

A2:修改每条记录的RN_C1:当DOPIS_C 不为空时,如果当前记录的 CP 与上一条记录的 CP 相同,即同一组数据内,则返回 t+1;如果跨组,则将 t 置为 1 并返回。如果 DOPIS_C 为空,则将 t 置为 null 并返回。注意变量 t 的初始默认值是 null。

问题来源:https://stackoverflow.com/questions/78341522/cumulative-totals-in-oracle-sql