Postgres 类似于 SQL Server 中的 CROSS APPLY [英] Postgres analogue to CROSS APPLY in SQL Server

查看:30
本文介绍了Postgres 类似于 SQL Server 中的 CROSS APPLY的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要将为 MS SQL Server 2005 编写的 SQL 查询迁移到 Postgres 9.1.
在此查询中替换 CROSS APPLY 的最佳方法是什么?

I need to migrate SQL queries written for MS SQL Server 2005 to Postgres 9.1.
What is the best way to substitute for CROSS APPLY in this query?

SELECT *
FROM V_CitizenVersions         
CROSS APPLY     
       dbo.GetCitizenRecModified(Citizen, LastName, FirstName, MiddleName,
BirthYear, BirthMonth, BirthDay, ..... ) -- lots of params

GetCitizenRecModified() 函数是一个表值函数.这个函数的代码我放不下,因为它真的很大,计算起来很困难,我不能放弃.

GetCitizenRecModified() function is a table valued function. I can't place code of this function because it's really enormous, it makes some difficult computations and I can't abandon it.

推荐答案

在 Postgres 9.3 或更高版本中使用 LATERAL 加入:>

In Postgres 9.3 or later use a LATERAL join:

SELECT v.col_a, v.col_b, f.*  -- no parentheses here, f is a table alias
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 or RETURNS SETOF record OR 退货记录):

For older versions, there is a very simple way to accomplish what I think you are trying to with a set-returning function (RETURNS TABLE or RETURNS SETOF record OR RETURNS record):

SELECT *, (f_citizen_rec_modified(col1, col2)).*
FROM   v_citizenversions v

该函数为外部查询的每一行计算一次值.如果函数返回多行,结果行会相应地相乘.所有括号在语法上都是必需的来分解行类型.表函数可能如下所示:

The function computes values once for every row of the outer query. If the function returns multiple rows, resulting rows are multiplied accordingly. All parentheses are syntactically required to decompose a row type. The table function could look something like this:

CREATE OR REPLACE FUNCTION f_citizen_rec_modified(_col1 int, _col2 text)
  RETURNS TABLE(col_c integer, col_d text) AS
$func$
SELECT s.col_c, s.col_d
FROM   some_tbl s
WHERE  s.col_a = $1
AND    s.col_b = $2
$func$ LANGUAGE sql;

如果要应用 WHERE 子句,则需要将其包装在子查询或 CTE 中,因为列在同一级别不可见.(无论如何,这对性能更好,因为您可以防止对函数的每个输出列进行重复评估):

You need to wrap this in a subquery or CTE if you want to apply a WHERE clause because the columns are not visible on the same level. (And it's better for performance anyway, because you prevent repeated evaluation for every output column of the function):

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;

还有其他几种方法可以做到这一点或类似的事情.这完全取决于您究竟想要什么.

There are several other ways to do this or something similar. It all depends on what you want exactly.

这篇关于Postgres 类似于 SQL Server 中的 CROSS APPLY的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆