Oracle Функция рекурсивного запаздывания - PullRequest
0 голосов
/ 02 марта 2020

У меня есть такие данные:

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)            

Он правильно определил число NEW_OPEN_AT_BEG для февраля как 32. Однако март равен null для NEW_OPEN_AT_BEG, поскольку функция задержки не является рекурсивной.

Как написать рекурсивную функцию запаздывания для сбора данных за предыдущий месяц и использования в расчетах?

1 Ответ

1 голос
/ 02 марта 2020

Я думаю, вам нужны кумулятивные суммы:

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;

Здесь - это дб <> скрипка.

...