Oracle 递归滞后函数

Oracle Recursive Lag Function

我有这样的数据:

MON   MONTH_NUM  OPEN_AT_BEG  OPENED  CLOSED
Jan   1          34           19      21
Feb   2          (null)       12      12
Mar   3          (null)       10      8 
Apr   4          (null)       (null)  (null)
May   5          (null)       (null)  (null)
Jun   6          (null)       (null)  (null)

此数据是使用此代码创建的:

select 'Jan' mon, 1 month_num, 34 open_at_beg, 19 opened, 21 closed from dual
union select 'Feb', 2 month_num, null open_at_beg, 12 opened, 12 closed from dual
union select 'Mar', 3 month_num, null open_at_beg, 10 opened, 8 closed from dual
union select 'Apr', 4 month_num, null open_at_beg, null opened, null closed from dual
union select 'May', 5 month_num, null open_at_beg, null opened, null closed from dual
union select 'Jun', 6 month_num, null open_at_beg, null opened, null closed from dual
order by month_num

我想做一件事:

最终结果应该是这样的:

MON   MONTH_NUM  OPEN_AT_BEG  OPENED  CLOSED  NEW_OPEN_AT_BEG
Jan   1          34           19      21      34               
Feb   2          (null)       12      12      32               
Mar   3          (null)       10      8       32              
Apr   4          (null)       (null)  (null)  (null)           
May   5          (null)       (null)  (null)  (null)           
Jun   6          (null)       (null)  (null)  (null)          

此结果基于今天是四月,因此所有内容都填写到上个月(三月)。

我试过了...

with test as (
select 'Jan' mon, 1 month_num, 34 open_at_beg, 19 opened, 21 closed from dual
union select 'Feb', 2 month_num, null open_at_beg, 12 opened, 12 closed from dual
union select 'Mar', 3 month_num, null open_at_beg, 10 opened, 8 closed from dual
union select 'Apr', 4 month_num, null open_at_beg, null opened, null closed from dual
union select 'May', 5 month_num, null open_at_beg, null opened, null closed from dual
union select 'Jun', 6 month_num, null open_at_beg, null opened, null closed from dual
order by month_num
)

select test.*, 
       case when month_num = 1 then open_at_beg 
            else lag(open_at_beg + opened - closed,1,0) over(order by month_num) 
       end new_open_at_beg
from test
order by month_num

这导致了这个...

MON   MONTH_NUM  OPEN_AT_BEG  OPENED  CLOSED  NEW_OPEN_AT_BEG
Jan   1          34           19      21      34
Feb   2          (null)       12      12      32
Mar   3          (null)       10      8       (null)
Apr   4          (null)       (null)  (null)  (null)
May   5          (null)       (null)  (null)  (null)
Jun   6          (null)       (null)  (null)  (null)            

它正确地将 2 月的 NEW_OPEN_AT_BEG 数字识别为 32。但是,对于 NEW_OPEN_AT_BEG,3 月是 null,因为滞后函数不是递归的。

如何编写递归滞后函数来获取上个月的数据并用于计算?

我想你想要的是累计金额:

select t.*,
       (case when open_at_beg is not null then open_at_beg
             when closed is not null and opened is not null
             then (sum(open_at_beg) over () +
                   sum(opened - closed) over (order by month_num rows between unbounded preceding and 1 preceding)
                  )
        end) as new_open_at_beg
from test t;

Here 是一个 db<>fiddle.