Упорядоченная итерация в пользовательской статистической функции? - PullRequest
3 голосов
/ 14 февраля 2012

Я только что реализовал интерфейс ODCIAggregate для создания пользовательской функции агрегирования.Он работает довольно хорошо и быстро, но я бы хотел сделать что-то еще.У меня есть следующее утверждение:

SELECT SomeId, myAggregationFunction(Item) FROM
(
  SELECT 
    Foo.SomeId, 
    SomeType(Foo.SomeValue, Foo.SomeOtherValue) AS Item
  FROM
    Foo
  ORDER BY Foo.SomeOrderingValue
)
GROUP BY SomeId;

Моя проблема в том, что элементы не передаются в функцию ODCIAggregateIterate моей реализации в том же порядке, в котором их внутренний (упорядоченный) SELECT возвращает их.

Я погуглил и не нашел ни одного предоставленного Oracle способа сделать это.Кто-нибудь из вас экспериментировал с подобной проблемой, основываясь на этом требовании?

Спасибо!

Ответы [ 2 ]

4 голосов
/ 19 февраля 2012

Рассматривали ли вы использование COLLECT вместо картриджа данных?

По крайней мере, для агрегирования строк метод COLLECT проще и намного быстрее.Это делает ваш SQL немного страннее.

Ниже приведен пример использования простой конкатенации строк.

--Create a type
create or replace type sometype as object
(
    someValue varchar2(100),
    someOtherValue varchar2(100)
);

--Create a nested table of the type.
--This is where the performance improvement comes from - Oracle can aggregate
--the types in SQL using COLLECT, and then can process all the values at once.
--This significantly reduces the context switches between SQL and PL/SQL, which
--are usually more expensive than the actual work.
create or replace type sometypes as table of sometype;

--Process all the data (it's already been sorted before it gets here)
create or replace function myAggregationFunction(p_sometypes in sometypes)
return varchar2 is
    v_result varchar2(4000);
begin
    --Loop through the nested table, just concatenate everything for testing.
    --Assumes a dense nested table
    for i in 1 .. p_sometypes.count loop
        v_result := v_result || ',' ||
            p_sometypes(i).someValue || '+' || p_sometypes(i).someOtherValue;
    end loop;

    --Remove the first delimeter, return value
    return substr(v_result, 2);
end;
/

--SQL
select someId
    ,myAggregationFunction
    (
        cast
        (
            --Here's where the aggregation and ordering happen
            collect(sometype(SomeValue, SomeOtherValue)
                order by SomeOrderingValue)
            as someTypes
        )
    ) result
from
(
    --Test data: note the unordered SoemOrderingValue.
    select 1 someId, 3 SomeOrderingValue, '3' SomeValue, '3' SomeOtherValue
    from dual union all
    select 1 someId, 1 SomeOrderingValue, '1' SomeValue, '1' SomeOtherValue
    from dual union all
    select 1 someId, 2 SomeOrderingValue, '2' SomeValue, '2' SomeOtherValue
    from dual
) foo
group by someId;

--Here are the results, aggregated and ordered.
SOMEID  RESULT
------  ------
1       1+1,2+2,3+3
0 голосов
/ 20 февраля 2012

Oracle, скорее всего, переписывает ваш запрос и избавляется от подзапроса.Я никогда не делал ничего подобного тому, что вы делаете, но не могли бы вы добавить подсказку NO_UNNEST к внутреннему запросу?

SELECT SomeId, myAggregationFunction(Item) FROM
(
  SELECT /*+ NO_UNNEST */
    Foo.SomeId, ...

Даже тогда я действительно не уверен, что это будет делатьЗАКАЗАТЬ внутри подзапроса.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...