如何重写一个选择。。。横向交叉连接。。。用于较旧PostgreSQL版本的语句?

如何重写一个选择。。。横向交叉连接。。。用于较旧PostgreSQL版本的语句?,sql,postgresql,postgresql-9.3,lateral,Sql,Postgresql,Postgresql 9.3,Lateral,我面临一个类似的问题: SELECT * FROM invoicable_interval i, LATERAL partition_into_months(i.start_date, i.stop_or_current_date) p; CREATE FUNCTION partition_into_months(start_date DATE, stop_date DATE) RETURNS TABLE (start_date DATE, stop_date DATE, days I

我面临一个类似的问题:

SELECT *
FROM invoicable_interval i,
  LATERAL partition_into_months(i.start_date, i.stop_or_current_date) p;
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;
。。。其中,将_划分为_个月的定义与此类似:

SELECT *
FROM invoicable_interval i,
  LATERAL partition_into_months(i.start_date, i.stop_or_current_date) p;
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.开始日期”中的点


如何重写此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;
但是,这可能会导致对每个返回列的
分区的一次调用,因为
(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)


第二个示例看起来很有趣,但我得到“[42P01]错误:表“I”位置的子句条目中缺少:8”找到了一个修复:您需要编写“SELECT(x.I)。*,(x.p)。*FROM…”。您介意更新您的解决方案吗?然后我将选择它。在我看来,该函数可以被(聚合)视图和/或generate_series()替换。显然,这取决于函数的主体。