如何为旧的 PostgreSQL 版本重写 SELECT ... CROSS JOIN LATERAL ... 语句?
How to rewrite a SELECT ... CROSS JOIN LATERAL ... statement for older PostgreSQL versions?
我遇到了类似这样的查询:
SELECT *
FROM invoicable_interval i,
LATERAL partition_into_months(i.start_date, i.stop_or_current_date) p;
... 其中 partition_into_months 的定义类似于:
CREATE FUNCTION partition_into_months(start_date DATE, stop_date DATE)
RETURNS TABLE (start_date DATE, stop_date DATE, days INT)
AS $$ ... $$
LANGUAGE sql
IMMUTABLE;
所以我正在为次要 table 进行可变间隔的交叉连接,因此(冗余)关键字 LATERAL。
这适用于 PostgreSQL 9.3.6 和 9.4.2,但是,对于 9.1.3,我收到以下错误消息:
[42601] ERROR: syntax error at or near "."
Position: 398
表示的位置是表达式"i.start_date".
中的点
如何重写此 SQL 查询以便将其移植回 PostgreSQL 9.1.3?
PostgreSQL 支持在 SELECT
子句中调用集合返回函数。现在我们有 LATERAL
并且肯定不鼓励这样做,因为它的行为相当不稳定,但它仍然有用。
在你的情况下你可以这样写:
SELECT
i.*,
(partition_into_months(i.start_date, i.stop_or_current_date)).*
FROM invoicable_interval i;
但是,这可能会导致每列返回一次 partition_into_months
调用,因为 (fn).*
基本上被宏扩展为 (fn).col1, (fn).col2, ...
。为避免这种情况,您可以将其包装在子查询中,例如
SELECT (x.i).*, (x.p).*
FROM
(
SELECT
i,
partition_into_months(i.start_date, i.stop_or_current_date) p
FROM invoicable_interval i
) x(i,p);
请注意,如果 SELECT
列表中存在多个集合返回函数,将会遇到奇怪的结果。它不是您所期望的交叉连接。例如,比较:
SELECT generate_series(1,4), generate_series(1,4)
至
SELECT generate_series(1,4), generate_series(1,3);
我遇到了类似这样的查询:
SELECT *
FROM invoicable_interval i,
LATERAL partition_into_months(i.start_date, i.stop_or_current_date) p;
... 其中 partition_into_months 的定义类似于:
CREATE FUNCTION partition_into_months(start_date DATE, stop_date DATE)
RETURNS TABLE (start_date DATE, stop_date DATE, days INT)
AS $$ ... $$
LANGUAGE sql
IMMUTABLE;
所以我正在为次要 table 进行可变间隔的交叉连接,因此(冗余)关键字 LATERAL。
这适用于 PostgreSQL 9.3.6 和 9.4.2,但是,对于 9.1.3,我收到以下错误消息:
[42601] ERROR: syntax error at or near "."
Position: 398
表示的位置是表达式"i.start_date".
中的点如何重写此 SQL 查询以便将其移植回 PostgreSQL 9.1.3?
PostgreSQL 支持在 SELECT
子句中调用集合返回函数。现在我们有 LATERAL
并且肯定不鼓励这样做,因为它的行为相当不稳定,但它仍然有用。
在你的情况下你可以这样写:
SELECT
i.*,
(partition_into_months(i.start_date, i.stop_or_current_date)).*
FROM invoicable_interval i;
但是,这可能会导致每列返回一次 partition_into_months
调用,因为 (fn).*
基本上被宏扩展为 (fn).col1, (fn).col2, ...
。为避免这种情况,您可以将其包装在子查询中,例如
SELECT (x.i).*, (x.p).*
FROM
(
SELECT
i,
partition_into_months(i.start_date, i.stop_or_current_date) p
FROM invoicable_interval i
) x(i,p);
请注意,如果 SELECT
列表中存在多个集合返回函数,将会遇到奇怪的结果。它不是您所期望的交叉连接。例如,比较:
SELECT generate_series(1,4), generate_series(1,4)
至
SELECT generate_series(1,4), generate_series(1,3);