объединить результаты многократного вызова одной и той же функции

У меня есть функция func1(integer);, она возвращает строки: partid,qty, например: select * from func1(1);

partid,qty
 10     50
 20     30

select * from func1(2);

partid,qty
 10     5
 20     30
 11     10

Мне нужно написать функцию, которая вызывает func1 с массивом и группирует по результатам. func2(integer[]);

например: select * from func2(array[1,2]); должен дать:

partid,qty
 10     55
 20     60
 11     10

Я написал это:

CREATE OR REPLACE FUNCTION func2(listx integer[])
  RETURNS SETOF records_d AS
$BODY$
declare
    item integer;
begin
    foreach item in array listx loop
        select * from func1(item);

    end loop;
end;
$BODY$
  LANGUAGE plpgsql VOLATILE

Record_d — это тип (целое число, целое число)

Эта функция не работает... Я не знаю, как объединить результаты разных итераций func1(), а затем вернуть их.


person java    schedule 04.01.2016    source источник
comment
Можете ли вы попробовать создать глобальную временную таблицу и в функции вставить нужные данные в таблицу, как только вы получите то, что хотите, вы можете просто удалить таблицу?   -  person Veljko89    schedule 04.01.2016
comment
Я думал об этом, но мне было интересно, возможно ли это без использования таблиц.   -  person java    schedule 04.01.2016
comment
Вы можете изменить выбор в foreach на return query select * from func1(item) и выполнить группировку во внешнем запросе: SELECT partid,sum(qty) as qty FROM func2(array[1,2]) GROUP BY partid   -  person Ctx    schedule 04.01.2016
comment
Или, поскольку они возвращают один и тот же набор результатов ... вы можете попробовать использовать Union?   -  person Veljko89    schedule 04.01.2016
comment
@ Ctx я не понимаю твоего решения. вне func2() нет. Вы предлагаете также написать func3()?   -  person java    schedule 04.01.2016
comment
@ Veljko89 В массиве, который я отправляю в func2, может быть 1000 элементов. как союз может справиться с этим?   -  person java    schedule 04.01.2016
comment
Почему бы вам не расширить func1() для поддержки массива? Можете ли вы показать нам код func1() и запрос, который он выполняет?   -  person a_horse_with_no_name    schedule 04.01.2016
comment
Либо func3(), либо в запросе, который вызывает func2().   -  person Ctx    schedule 04.01.2016
comment
@a_horse_with_no_name код, который я пишу, будет использоваться только один раз. func1() — это существующая функция в моей БД. Я хотел просто использовать его. Я думал, что может быть простое решение, но если его нет, я просто скопирую func1() в другое место и отредактирую его для поддержки массива.   -  person java    schedule 04.01.2016
comment
а как же простой союз? select partid,sum(qty) from (select partid,qty from func1(2) union all select partid,qty from func1(1)) t group by partid?   -  person a_horse_with_no_name    schedule 04.01.2016
comment
Я не знаю, сколько элементов в listx. Он также может иметь 1000 элементов.   -  person java    schedule 04.01.2016


Ответы (2)


Для этого вам не нужна другая функция, вы можете сделать это в одном операторе SQL:

select f.partid, sum(f.qty)
from unnest(array[1,2]) i, func1(i) f
group by f.partid;

Пример SQLFiddle: http://sqlfiddle.com/#!15/8b083/1

person a_horse_with_no_name    schedule 04.01.2016
comment
Вау... это определенно улучшенный кусок кода. :) - person T.Z.; 04.01.2016

Как это часто бывает с postgres, у него есть RETURN NEXT. пункт, который именно то, что вы хотите.

Я думаю, вам придется скорректировать код, чтобы привести результаты innes select к типу records_d. Но RETURN NEXT - это то, что вам нужно.

CREATE OR REPLACE FUNCTION getAllFoo() RETURNS SETOF foo AS
$BODY$
DECLARE
    r foo%rowtype;
BEGIN
    FOR r IN SELECT * FROM foo
    WHERE fooid > 0
    LOOP
        -- can do some processing here
        RETURN NEXT r; -- return current row of SELECT
    END LOOP;
    RETURN;
END
$BODY$
LANGUAGE 'plpgsql' ;
person T.Z.    schedule 04.01.2016