Вызывать функцию, возвращающую множество, с аргументом массива несколько раз
Это разновидность функции plpgsql, которая возвращает несколько столбцов, вызываемых несколько раз. Однако я надеялся найти решение моих конкретных обстоятельств.
У меня есть функция, которая обрабатывает массив строк с заданным параметром и возвращает набор строк + новый столбец.
CREATE OR REPLACE foo(data data[], parameter int) RETURNS SETOF enhanceddata AS
...
Функция работает на тестовом примере только с 1 набором данных
SELECT * FROM foo( (SELECT ARRAY_AGG(data) FROM datatable GROUP BY dataid WHERE dataid = something), 1)
Но я бы хотел, чтобы он работал с несколькими группами данных, не передавая dataid
к функции. Я попробовал несколько вариантов:
SELECT dataid, (foo(ARRAY_AGG(data)),1).*
FROM dataset
WHERE dataid = something -- only testing on 1
GROUP BY dataid
Но функция вызывается один раз для каждого столбца.
2 ответа
В Postgres 9.3 или новее лучше всего использовать (LEFT
) JOIN LATERAL
,
SELECT sub.dataid, f.*
FROM (
SELECT dataid, array_agg(data) AS arr
FROM dataset
WHERE dataid = something
GROUP BY 1
) sub
LEFT JOIN LATERAL foo(sub.arr) f ON true;
Если функция foo()
не может вернуть строки, безопасная форма с LEFT JOIN LATERAL
как продемонстрировано. Иначе, или если вы хотите исключить строки без результата из бокового соединения, используйте JOIN LATERAL
или его сокращенный эквивалент:
, foo(sub.arr)
Это явно упоминается в руководстве.
Я обновил соответствующий ответ Крейга (на который ссылается Дэниел) соответственно:
В этом контексте функция вызывается несколько раз не из-за ее входных данных, а из-за того, как func().*
реализуется
Это объясняется по адресу: Как избежать множественных ошибок функций с помощью синтаксиса (func()).* В запросе SQL?
Следующий вариант должен работать без нескольких evals на всех поддерживаемых версиях PostgreSQL (8.4 или новее):
WITH subq as (
SELECT array_agg(data) as agg,
dataid FROM datatable
-- WHERE clause ?
GROUP BY dataid)
SELECT foo(agg,dataid) FROM subq;