在Postgres 9.3或更新版本中,使用LATERAL
连接:
SELECT v.col_a, v.col_b, f.*
FROM v_citizenversions v
LEFT JOIN LATERAL f_citizen_rec_modified(v.col1, v.col2) f ON true
WHERE f.col_c = _col_c;
为什么要使用LEFT JOIN LATERAL ... ON true
?
对于旧版本,有一种非常简单的方法可以通过返回一个集合的函数(RETURNS TABLE
或RETURNS SETOF record
或RETURNS record
)来实现我认为你试图实现的功能:
SELECT *, (f_citizen_rec_modified(col1, col2)).*
FROM v_citizenversions v
该函数针对外查询的每一行计算一次值。如果函数返回多行,结果行相应地进行乘法运算。为了分解行类型,所有括号在语法上都是必需的。表函数可能如下所示:
CREATE OR REPLACE FUNCTION f_citizen_rec_modified(_col1 int, _col2 text)
RETURNS TABLE(col_c integer, col_d text)
LANGUAGE sql AS
$func$
SELECT s.col_c, s.col_d
FROM some_tbl s
WHERE s.col_a = $1
AND s.col_b = $2
$func$;
如果您想应用WHERE
子句,因为这些列在同一级别上不可见,所以您需要将其包装在子查询或CTE中。(而且出于性能考虑,这样做更好,因为您可以防止函数的每个输出列重复评估):
SELECT col_a, col_b, (f_row).*
FROM (
SELECT col_a, col_b, f_citizen_rec_modified(col1, col2) AS f_row
FROM v_citizenversions v
) x
WHERE (f_row).col_c = _col_c;
还有几种其他方法可以实现这个或类似的需求。具体取决于你想要什么。
CROSS APPLY
会使用相关参数重新执行 TVF,而不是执行一次然后连接结果。 - Martin Smithapply
优化为join
的说明:http://www.sqlservercentral.com/articles/APPLY/69954/ 由于我们在这里看不到原始代码,所以我根据对Erwin答案性能的评论进行了推测。 - Davos