我正在尝试连接返回行的表和函数:
SELECT p.id, p.name, f.action, f.amount
FROM person p
JOIN calculate_payments(p.id) f(id, action, amount) ON (f.id = p.id);
此函数为每个id返回0,1行或更多行。 该查询适用于PostgreSQL 9.3,但在 9.1 上显示以下错误:
ERROR: invalid reference to FROM-clause entry for table "p" HINT: There is an entry for table "p", but it cannot be referenced from this part of the query
我无法将函数中的计算移出到查询中 根据我的理解,我不能使用 JOIN LATERAL 这是9.3中的新功能 这个问题有解决办法吗?
答案 0 :(得分:9)
Postgres 9.1 :
SELECT name, (f).* -- note the parentheses!
FROM (SELECT name, calculate_payments(id) AS f FROM person) sub;
假设您的函数具有明确定义的返回类型,其列名为(id, action, amount)
- 问题中缺少信息。
还假设你的函数总是返回相同的id
它被馈送(在这种情况下这是多余的,可能会被优化)。
相同的更详细的形式:
SELECT sub.id, sub.name, (sub.f).action, (sub.f).amount -- parentheses!
FROM (
SELECT p.id, p.name, calculate_payments(p.id) AS f(id, action, amount)
FROM person p
) sub;
SELECT
列表中的设置返回函数会产生多行。但这是一个非标准的,有些古怪的特征。 pg 9.3+中的新LATERAL
功能更可取。
您可以在同一步骤中分解行类型:
SELECT *, (calculate_payments(p.id)).* -- parentheses!
FROM person p
但是由于Postgres查询规划器的弱点,这导致每列评估一次函数:
或者在你的情况下:
SELECT p.id, p.name
, (calculate_payments(p.id)).action
, (calculate_payments(p.id)).amount
FROM person p
同样的问题:多重评估。
准确地说,第9.3页中的解决方案的等价物是:
SELECT p.id, p.name, f.action, f.amount
FROM person p
LEFT JOIN LATERAL calculate_payments(p.id) f ON TRUE;
保留结果中的行,其中函数返回0行。
如果您不关心这一点,可以简化第9.3 +:
页SELECT p.id, p.name, f.action, f.amount
FROM person p, calculate_payments(p.id) f;
密切相关的答案: