SQL 对于嵌套的 WITH 子句 - Oracle 19c 中的结果偏移

SQL for nested WITH CLAUSE - RESULTS OFFSET in Oracle 19c

请提出一种实现 (temp - results - select) 嵌套的方法,如下所示?

我看到 oracle 19c 不允许嵌套 WITH 子句。

with temp2 as   
(   
    with temp1 as
    (
        __
        __
    ),
    results(..fields..) as
    (
        select ..<calc part>.. from temp1, results where __
    )   
    select ..<calc part>.. from temp1 join results where __
    
),
results(..fields..) as
(
    select ..<calc part>.. from temp2, results where __
)   
select ..<calc part>.. from temp2 join results where __

例如:

DB Fiddle

我需要以与 CALC

类似的递归方式计算 CALC3

CREATE TABLE TEST ( DT DATE, NAME VARCHAR2(10), VALUE NUMBER(10,3));

insert into TEST values ( to_date( '01-jan-2021'), 'apple', 198.95 );
insert into TEST values ( to_date( '02-jan-2021'), 'apple', 6.15 );
insert into TEST values ( to_date( '03-jan-2021'), 'apple', 4.65 );
insert into TEST values ( to_date( '06-jan-2021'), 'apple', 20.85 );
insert into TEST values ( to_date( '01-jan-2021'), 'banana', 80.5 );
insert into TEST values ( to_date( '02-jan-2021'), 'banana', 9.5 );
insert into TEST values ( to_date( '03-jan-2021'), 'banana', 31.65 );

--Existing working code - 

with t as
 ( select
     test.*,
     row_number() over ( partition by name order by dt ) as seq
   from test
 ),
 results(name, dt, value, calc ,seq) as
 (
   select name, dt, value, value/5 calc, seq
   from t
   where seq = 1
   union all
   select t.name, t.dt, t.value, ( 4 * results.calc + t.value ) / 5, t.seq
   from t, results
   where t.seq - 1 = results.seq
   and  t.name = results.name
 )
 select results.*, calc*3 as calc2  -- Some xyz complex logic as calc2
 from results
 order by name, seq;

期望输出:

CALC3 - 按名称和 dt 分组 -

((CALC3 of prev day record * 4) + CALC2 of current record )/ 5

i.e for APPLE 
for 1-jan-21, CALC = ((0*4)+119.37)/5 = 23.87 -------> since it is 1st record, have taken 0 as CALC3 of prev day record
for 2-jan-21, CALC = ((23.87*4)+99.19)/5= 115.33 -----> prev CALC3 is considered from 1-jan-21 - 23.87 and 99.19 from current row
for 3-jan-21, CALC = ((115.33*4)+82.14)/5= 477.76 and so on

For BANANA
1-jan-21, CALC = ((0*4)+48.30)/5=9.66
1-jan-21, CALC = ((9.66*4)+44.34)/5=47.51 
etc

不需要,一个关卡就可以:

with temp1(...fields...) as
(
    __
    __
    __
),
results1(...fields...) as
(
  select ...<calc part>... from temp1 where __
),
temp2( ...fields...) as   
(   
    select ...<calc part>... from temp1 join results1 where __
),
results2(...fields...) as
(
    select ...<calc part>... from temp2 where __
)   
select ...<calc part>... from temp2 join results2 where __

对于你的实际问题,你可以使用MODEL子句:

SELECT dt,
       name,
       amount,
       calc,
       seq,
       calc2,
       calc3
FROM   (
  SELECT t.*,
         ROW_NUMBER() OVER (PARTITION BY name ORDER BY dt) AS seq
  FROM   test t
)
MODEL
  PARTITION BY (name)
  DIMENSION BY (seq)
  MEASURES ( dt, amount, 0 AS calc, 0 AS calc2, 0 as calc3)
  RULES (
    calc[1] = amount[1]/5,
    calc[seq>1] = (amount[cv(seq)] + 4*calc[cv(seq)-1])/5,
    calc2[seq] = 3*calc[cv(seq)],
    calc3[1] = calc2[1]/5,
    calc3[seq>1] = (calc2[cv(seq)] + 4*calc3[cv(seq)-1])/5
  )

输出:

DT NAME AMOUNT CALC SEQ CALC2 CALC3
01-JAN-21 banana 80.5 16.1 1 48.3 9.66
02-JAN-21 banana 9.5 14.78 2 44.34 16.596
03-JAN-21 banana 31.65 18.154 3 54.462 24.1692
01-JAN-21 apple 198.95 39.79 1 119.37 23.874
02-JAN-21 apple 6.15 33.062 2 99.186 38.9364
03-JAN-21 apple 4.65 27.3796 3 82.1388 47.57688
06-JAN-21 apple 20.85 26.07368 4 78.22104 53.705712

db<>fiddle here