我面临类似的问题:
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;
所以我正在使用辅助表的可变间隔进行交叉连接,因此(冗余)关键字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?
答案 0 :(得分:1)
PostgreSQL支持在SELECT
子句中调用set-returns函数。由于我们有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);