Функция plpgsql, которая возвращает несколько столбцов, вызывается несколько раз

Я использую PostgreSQL 9.2.1 и у меня есть функция plpgsql, которая возвращает 3 столбца. Это называется так (упрощенно):

SELECT (my_function(b.input)).*, a.other, b.columns
FROM table_a a
JOIN table_b b ON a.id = b.id
WHERE ...

Функция выводит сообщение ПРЕДУПРЕЖДЕНИЕ, и я был удивлен, обнаружив, что оно напечатано 3 раза. Похоже, что функция вызывается 3 раза - предположительно один раз для каждого столбца. Это не может быть хорошо для производительности! Как я могу убедиться, что он вызывается только один раз? Он уже отмечен как СТАБИЛЬНЫЙ.

Если я называю это как

SELECT * FROM my_function(input)

тогда предупреждение выводится только один раз, но я не знаю, как я могу интегрировать это в больший запрос с возвращаемыми объединениями и другими столбцами. То есть я не знаю, как поместить функцию в список FROM, когда мне требуются другие таблицы в списке FROM, и функция берет свои данные из них.

Редактировать:

Запрос (намного ближе к оригиналу):

SELECT (my_aggregate_function(sub1.border, sub1.lower_limit, sub1.upper_limit, operation)).*
FROM
(
    SELECT (my_function(ca.timeslice_id)).*, agc.operation
    FROM geometry_component agc
    JOIN volume av ON agc.volume_id = av.id
    JOIN volume_dependency avd ON av.contributor_id = avd.id
    JOIN my_rowset_function('2013-02-22') ca ON avd.id = ca.feature_id
    WHERE agc.timeslice_id = 12345
    ORDER BY agc.sequence
) sub1

my_aggregate_function а также my_function каждый возвращает 3 столбца (border, lower_limit, upper_limit), но my_aggregate_function это совокупность и my_function это обычная функция.

2 ответа

Решение

Это должно сделать работу:

SELECT (y).*
FROM  (
   SELECT my_aggregate_function(border, lower_limit, upper_limit, operation) AS y
   FROM (
      SELECT (x).*, operation
      FROM  (
         SELECT my_function(ca.timeslice_id) AS x, agc.operation
         FROM   geometry_component agc
         JOIN   volume             av  ON av.id = agc.volume_id
         JOIN   volume_dependency  avd ON avd.id = av.contributor_id
         JOIN   my_rowset_function('2013-02-22') ca ON ca.feature_id = avd.id
         WHERE  agc.timeslice_id = 12345
         ORDER  BY agc.sequence
         ) sub1
      )sub2
   )sub3

К сожалению, это обычная особенность реализации. Можно будет избежать этой проблемы, когда поддержка LATERAL запросы идут с 9.3.

На данный момент я не знаю ни одного хорошего обходного пути.

Другие вопросы по тегам