Вызывать функцию, возвращающую множество, с аргументом массива несколько раз

Это разновидность функции 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;
Другие вопросы по тегам