patternMinor
Product of n Rows
Viewed 0 times
rowsproductstackoverflow
Problem
From this data (assuming the number of rows is not known in advance):
I want the product of the c1 column from all the rows. Something like the results of SUM(c1) only I want each value multiplied by they others rather than added. In this case that would be 2 1 4 * 1 = 8.
Data could contain negative numbers and zero, which can be simulated using:
or
I know this could be done with custom aggregate function, but am interested in native approaches.
with q1 as (select mod(ora_hash(level),5) c1 from dual connect by level <=4)
select * from q1;
/*
C1
--
2
1
4
1
*/I want the product of the c1 column from all the rows. Something like the results of SUM(c1) only I want each value multiplied by they others rather than added. In this case that would be 2 1 4 * 1 = 8.
/*
X1
--
8
*/Data could contain negative numbers and zero, which can be simulated using:
with q1 as (select mod(ora_hash(level),5)-1 c1 from dual connect by level <=4)
select * from q1;or
with q1 as (select mod(ora_hash(level),5)-3 c1 from dual connect by level <=4)
select * from q1;I know this could be done with custom aggregate function, but am interested in native approaches.
Solution
For sufficiently small aggregate products, you can use the old trick of summing the logarithms and them exponentiating the result
Since you're using 11.2, it's a bit more verbose (though someone may be able to figure out a simpler version) but you can also use recursive common table expressions
SQL> ed
Wrote file afiedt.buf
1 with q1
2 as (select mod(ora_hash(level),5) c1
3 from dual
4 connect by level /
EXP(SUM(LN(C1)))
----------------
8Since you're using 11.2, it's a bit more verbose (though someone may be able to figure out a simpler version) but you can also use recursive common table expressions
SQL> ed
Wrote file afiedt.buf
1 with
2 q1 as (select level l, mod(ora_hash(level),5) c1
3 from dual
4 connect by level /
RUNNING_PRODUCT
---------------
8Code Snippets
SQL> ed
Wrote file afiedt.buf
1 with q1
2 as (select mod(ora_hash(level),5) c1
3 from dual
4 connect by level <=4)
5 select exp(sum(ln(c1)))
6* from q1
SQL> /
EXP(SUM(LN(C1)))
----------------
8SQL> ed
Wrote file afiedt.buf
1 with
2 q1 as (select level l, mod(ora_hash(level),5) c1
3 from dual
4 connect by level <= 4),
5 num(n, c1, running_product)
6 as
7 (
8 select 1 as N,
9 null as c1,
10 1 as running_product
11 from dual
12 union all
13 select N+1,
14 q1.c1,
15 (q1.c1)*running_product
16 from num
17 join q1 on (num.N = q1.l)
18 )
19 select running_product
20 from (select num.*,
21 rank() over (order by N desc) rnk
22 from num)
23* where rnk = 1
SQL> /
RUNNING_PRODUCT
---------------
8Context
StackExchange Database Administrators Q#15019, answer score: 5
Revisions (0)
No revisions yet.