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
我想做一件事:
- 创建一个新列
NEW_OPEN_AT_BEG
(NEW_OPEN_AT_BEG
= 上个月OPEN_AT_BEG
+ 上个月OPENED
- 上个月CLOSED
)
最终结果应该是这样的:
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.
我有这样的数据:
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
我想做一件事:
- 创建一个新列
NEW_OPEN_AT_BEG
(NEW_OPEN_AT_BEG
= 上个月OPEN_AT_BEG
+ 上个月OPENED
- 上个月CLOSED
)
最终结果应该是这样的:
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.