Это редко используется, но oracle позволяет вам определять ваши собственные агрегатные функции.
Все, что вам нужно сделать, это создать тип, который реализует методы ODCIAggregate, а затем создать функцию, которая использует этот тип.
Есть пример в oracle docs , см. Раздел «Пример 11-12 Как создать и использовать пользовательскую статистическую функцию».
Я в основном скопировал пример и изменил несколько строк:
create or replace type AGGR_MUL_TST as object
(
total number,
static function ODCIAggregateInitialize(ctx IN OUT AGGR_MUL_TST)
return number,
member function ODCIAggregateIterate(self IN OUT AGGR_MUL_TST,
value IN number)
return number,
member function ODCIAggregateTerminate(self IN AGGR_MUL_TST,
returnValue OUT number, flags IN number)
return number,
member function ODCIAggregateMerge(self IN OUT AGGR_MUL_TST,
ctx2 IN AGGR_MUL_TST)
return number
);
create or replace type body AGGR_MUL_TST is
static function ODCIAGGREGATEINITIALIZE(ctx in out AGGR_MUL_TST)
return number is
begin
ctx := AGGR_MUL_TST(1);
return ODCIConst.Success;
end;
member function ODCIAggregateIterate(self in out AGGR_MUL_TST,
value in number)
return number is
begin
self.total := self.total * value;
return ODCIConst.Success;
end;
member function ODCIAggregateTerminate(self in AGGR_MUL_TST,
returnValue out number,
flags in number
)
return number is
begin
returnValue := self.total;
return ODCIConst.Success;
end;
member function ODCIAggregateMerge(self in out AGGR_MUL_TST,
ctx2 IN AGGR_MUL_TST
)
return number is
begin
self.total := self.total * ctx2.total;
end;
end;
/
create or replace function AGGR_MUL(input number) return number parallel_enable aggregate using AGGR_MUL_TST;
/
Теперь вы можете использовать его в любом запросе, например, в обычной статистической функции:
with nums as (
select 1 x, 2 y from dual union all
select 2 x, 2 y from dual union all
select 3 x, 2 y from dual union all
select 4 x, 3 y from dual union all
select -5 x, 3 y from dual
)
select aggr_mul(x)
from nums
И даже с группой по:
with nums as (
select 1 x, 2 y from dual union all
select 2 x, 2 y from dual union all
select 3 x, 2 y from dual union all
select 4 x, 3 y from dual union all
select -5 x, 3 y from dual
)
select y,
aggr_mul(x)
from nums
group by y