2013-02-21 2 views
1

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

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 раза - предположительно один раз для каждого столбца. Это не может быть хорошо для производительности! Как я могу убедиться, что он вызван только один раз? Он уже отмечен STABLE.

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

SELECT * FROM my_function(input) 

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

Edit:

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

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 колонки (граница, lower_limit, верхняя_граница), но my_aggregate_function представляет собой совокупность и my_function - это обычная функция.

+0

Тесно связанный с этим вопрос со вчерашнего дня: http://stackoverflow.com/questions/14965708/insert-using-a-function-that-returns-two-values- за строкой. Пожалуйста, предоставьте свой запрос, возможно, будет реализован подзапрос. –

+0

Спасибо за ссылку, но я не мог понять это. Я добавил запрос. – EM0

ответ

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 
+0

Спасибо, Эрвин, ты - вопрос Джона Скита из PostgreSQL! – EM0

+0

Интересно, почему PostgreSQL не делает это так внутренне. Интересно, что агрегированная функция вызывалась только один раз (без описанного выше обхода), хотя она также возвращает несколько столбцов. По крайней мере, моя функция аккумулятора вызывалась только один раз в строке. – EM0

+0

@EM: О, какая честь для Джона Скита! ;) Я бы назвал это слабостью планировщика запросов в текущей версии. Разработчики Postgres сосредоточились на получении ['LATERAL'] (http://www.depesz.com/2012/08/19/waiting-for-9-3-implement-sql-standard-lateral-subqueries/) в версии 9.3 который должен обеспечить более эффективные способы решения подобных проблем. –

1

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

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

Смежные вопросы