2013-02-21 91 views
1

我正在运行PostgreSQL 9.2.1并且有一个返回3列的plpgsql函数。这就是所谓的(简化):返回多列的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次 - 大概每列一次。这对性能不好!我怎样才能确保它只被调用一次?它已经标记为稳定。

如果我把它作为

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_functionmy_function每个返回3列(边框,LOWER_LIMIT,UPPER_LIMIT),但my_aggregate_function是一个聚合和my_function是一个常规功能。

+0

密切相关的问题:http://stackoverflow.com/questions/14965708/insert-using-a-function-that-returns-two-values-每行。请提供您的查询,应该可以实现子查询。 – 2013-02-21 12:15:05

+0

感谢您的链接,但我无法从中找出答案。我已经添加了查询。 – EM0 2013-02-22 12:45:41

回答

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

谢谢Erwin,你是PostgreSQL问题的Jon Skeet! – EM0 2013-02-26 13:09:24

+0

我想知道为什么PostgreSQL在内部不这样做。有趣的是,聚合函数只被调用一次(没有上述解决方法),即使它也返回多个列。至少我的累加器函数每行只调用一次。 – EM0 2013-02-26 13:10:33

+0

@EM:噢,Jon Skeet多么荣幸! ;)我认为它是当前版本中查询规划器的弱点。 Postgres的开发人员专注于将['LATERAL'](http://www.depesz.com/2012/08/19/waiting-for-9-3-implement-sql-standard-lateral-subqueries/)转换为版本9.3这应该为这类问题提供更有效的方法。 – 2013-02-26 13:18:21

1

不幸的是,这是一个正常的实施怪癖。当对LATERAL查询的支持进入9.3时,将可以避免此问题。

现在我不知道任何好的解决方法。