Justin inspired me to attempt a version using the MODEL
clause. This is my first use of the clause, so I'm open to any constructive criticism. I created three CTEs to test negative numbers and zero.
with q1 as (select level N, mod(ora_hash(level),5) c1 from dual connect by level <=4),
q2 as (select N, c1-1 c1 from q1),
q3 as (select N, c1-3 c1 from q1)
select c1 from q1
model return updated rows dimension by (N) measures (c1)
rules iterate (999) until (c1[iteration_number+1] IS NULL) (
c1[1] = c1[1] * NVL(c1[iteration_number+2],1)
)
union all
select c1 from q2
model return updated rows dimension by (N) measures (c1)
rules iterate (999) until (c1[iteration_number+1] IS NULL) (
c1[1] = c1[1] * NVL(c1[iteration_number+2],1)
)
union all
select c1 from q3
model return updated rows dimension by (N) measures (c1)
rules iterate (999) until (c1[iteration_number+1] IS NULL) (
c1[1] = c1[1] * NVL(c1[iteration_number+2],1)
);
Here is a fleshed out version of the log solution that handles negative and zero values.
with q1 as (select mod(ora_hash(level),5) c1 from dual connect by level <=4),
q2 as (select c1-1 c1 from q1),
q3 as (select c1-3 c1 from q1)
select 'q1', case when sum(case when c1 < 0 then -1
when c1 > 0 then 1 else 0 end) >= 0 then 1 else -1 end *
decode(min(abs(c1)),0,0,Round(exp(sum(ln(abs(nullif(c1,0))))))) x1
from q1
union all
select 'q2', case when sum(case when c1 < 0 then -1
when c1 > 0 then 1 else 0 end) >= 0 then 1 else -1 end *
decode(min(abs(c1)),0,0,Round(exp(sum(ln(abs(nullif(c1,0))))))) x1
from q2
union all
select 'q3', case when sum(case when c1 < 0 then -1
when c1 > 0 then 1 else 0 end) >= 0 then 1 else -1 end *
decode(min(abs(c1)),0,0,Round(exp(sum(ln(abs(nullif(c1,0))))))) x1
from q3
;
Finally, here is a recursive CTE similar to Justins, but slightly simpler.
with q1 as (select level N, mod(ora_hash(level),5) c1 from dual connect by level <=4),
q2 as (select N, c1-1 c1 from q1),
q3 as (select N, c1-3 c1 from q1),
x1 (N, Product) as (
select 1 N, 1 Product from dual
union all
select x1.N+1 N, q1.c1 * x1.Product Product from x1
join q1 on (x1.N = q1.N)
),
x2 (N, Product) as (
select 1 N, 1 Product from dual
union all
select x2.N+1 N, q2.c1 * x2.Product Product from x2
join q2 on (x2.N = q2.N)
),
x3 (N, Product) as (
select 1 N, 1 Product from dual
union all
select x3.N+1 N, q3.c1 * x3.Product Product from x3
join q3 on (x3.N = q3.N)
)
select Product from (select N, Product, max(N) OVER () MaxN from x1) where N = MaxN
union all
select Product from (select N, Product, max(N) OVER () MaxN from x2) where N = MaxN
union all
select Product from (select N, Product, max(N) OVER () MaxN from x3) where N = MaxN;
SUM(LOG(...))
and aCASE
expression to handle0
and-ve
numbers.