Postgres 10或更新版本
对于较小的集合,使用空值填充。通过 generate_series()
演示:
SELECT generate_series( 1, 2) AS row2
, generate_series(11, 13) AS row3
, generate_series(21, 24) AS row4;
以下是翻译的结果:
第二行 | 第三行 | 第四行
-----+------+-----
1 | 11 | 21
2 | 12 | 22
null | 13 | 23
null | null | 24
dbfiddle 这里
Postgres 10 的手册:
如果查询的选择列表中有多个返回集函数,则行为类似于将这些函数放入单个
LATERAL ROWS FROM( ... )
FROM
-子句项中。对于基础查询结果集中的每一行,首先使用第一个函数返回的结果生成一行输出数据,接着使用第二个函数返回的结果生成另一行输出数据,如此类推。如果某些返回集函数产生的输出结果比其他函数少,则会用 null 值替换缺失的数据,以便对于一个基础行,发出的总行数与产生最多输出结果的返回集函数的行数相同。因此,这些返回集函数“同步执行”,直到它们全部耗尽,然后继续下一行基础行的处理。
这里结束了传统上的奇怪行为。
此重写还更改了一些其他细节。
发布说明:
更改查询的
SELECT
列表中出现的集合返回函数的实现方式,现在在评估标量表达式之前评估集合返回函数,就像将它们放置在一个
LATERAL FROM
子句项中一样。这允许更合理的语义,适用于存在多个集合返回函数的情况。如果它们返回不同行数,则通过添加nulls将较短的结果扩展到与最长结果匹配。以前的结果会循环直到它们同时终止,产生与函数周期的最小公倍数相等的行数。
此外,现在禁止在CASE
和COALESCE
结构中使用集合返回函数。有关更多信息,请参见
第37.4.8节。
结果行数(有点出乎意料!)是相同
SELECT
列表中所有集合的
最小公倍数。(只有当所有集合大小没有公共除数时才像
CROSS JOIN
!)示例:
SELECT generate_series( 1, 2) AS row2
, generate_series(11, 13) AS row3
, generate_series(21, 24) AS row4;
以下是翻译的内容:
第二行 | 第三行 | 第四行
-----+------+-----
1 | 11 | 21
2 | 12 | 22
1 | 13 | 23
2 | 11 | 24
1 | 12 | 21
2 | 13 | 22
1 | 11 | 23
2 | 12 | 24
1 | 13 | 21
2 | 11 | 22
1 | 12 | 23
2 | 13 | 24
dbfiddle 这里
在
Postgres 9.6手册的SQL Functions Returning Sets章节中有记录,建议避免在选择列表中使用返回集函数:
注意:将多个返回集函数放入同一选择列表中而不是FROM
子句的关键问题在于,这样做得到的实际输出行数等于每个返回集函数产生的行数的最小公倍数。调用多个返回集函数时,LATERAL
语法会产生更少令人惊讶的结果,并且通常应该使用它。
加粗强调是我的。
单个返回集函数是可以的(但在FROM
列表中更清晰),但是现在不鼓励在同一SELECT
列表中使用多个。在我们拥有LATERAL
连接之前,这是一个有用的功能。现在它只是历史负担。
相关: