我试图获得两个集合返回函数的结果的"交叉连接",但在某些情况下,我没有得到"交叉连接",参见示例
行为1:当集合长度相同时,从每个集合中逐项匹配
<>之前postgres=# SELECT generate_series(1,3), generate_series(5,7) order by 1,2;Generate_series | Generate_series-----------------+-----------------1 | 52 | 63 | 7(3行)之前行为2:当集合长度不同时,它"交叉连接"集合
<>之前postgres=# SELECT generate_series(1,2), generate_series(5,7) order by 1,2;Generate_series | Generate_series-----------------+-----------------1 | 51 | 61 | 72 | 52 | 62 | 7(6行)之前我想我这里没有理解什么,有人能解释一下预期的行为吗?
另一个更奇怪的例子:
<>之前postgres=# SELECT generate_series(1,2) x, generate_series(1,4) y order by x,y;X | y---+---1 | 11 | 32 | 22 | 4(4行)之前我正在寻找标题中问题的答案,理想情况下与链接(s)到文档。
Postgres 10及以上版本
填充符对于较小的集合具有空值。generate_series()
的演示:
SELECT generate_series( 1, 2) AS row2
, generate_series(11, 13) AS row3
, generate_series(21, 24) AS row4;
<>之前Row2 | row3 | row4-----+------+-----1 | 11 | 212 | 12 | 22null | 13 | 23null | null | 24之前dbfiddle这里
Postgres 10手册:
如果在查询的select中有多个set返回函数列表中,其行为类似于将函数变成单个
LATERAL ROWS FROM( ... )
FROM
子句项。为在基础查询的每一行中,都有一个使用第一个结果来自每个函数,然后是使用第二个函数的输出行结果,等等。如果某些集合返回函数产生输出比其他输出少,空值替换缺失的值数据,以便为一个基础行发出的行总数是否与产生最多结果的集合返回函数相同输出。因此,返回集合的函数"步调一致"地运行,直到它们都筋疲力尽,然后继续执行下一个底层行。
这结束了传统的奇怪行为。
这次重写更改了其他一些细节。发行说明:
改变在查询的
SELECT
列表中出现的set返回函数的实现(Andres Freund)返回集合的函数现在在计算标量之前求值表达式在
SELECT
列表中,就像它们已经被放置一样在LATERAL FROM
子句项中。这允许用例使用更合理的语义其中存在多个返回集合的函数。如果他们回来不同的行数,较短的结果扩展到匹配通过加空得到的最长结果。以前的结果是循环的直到它们全部同时终止,产生许多行等于函数周期的最小公倍数。在现在不允许在CASE
和COALESCE
结构。更多信息请参见37.4.8节。
粗体强调我的
Postgres 9.6及以上版本
结果行数(有点令人惊讶!)是同一SELECT
列表中所有集合的最小公共倍数。(只有在所有集合大小没有公约数的情况下才像CROSS JOIN
一样!)演示:
SELECT generate_series( 1, 2) AS row2
, generate_series(11, 13) AS row3
, generate_series(21, 24) AS row4;
<>之前Row2 | row3 | row4-----+------+-----1 | 11 | 212 | 12 | 221 | 13 | 232 | 11 | 241 | 12 | 212 | 13 | 221 | 11 | 232 | 12 | 241 | 13 | 212 | 11 | 221 | 12 | 232 | 13 | 24之前dbfiddle这里
Postgres 9.6手册SQL函数返回集章节,以及避免使用的建议:
注意:在select中使用set返回函数的关键问题列表,而不是
FROM
子句,是放置多个集合返回函数在同一选择列表中的表现不太好明智的。(如果这样做,您实际得到的是一些输出行数等于行数的最小公倍数)LATERAL
语法产生当调用多个集合返回函数时,结果并不令人惊讶,
粗体强调我的
单个set返回函数是可以的(但在FROM
列表中仍然更干净),但现在不鼓励在同一个SELECT
列表中使用多个set返回函数。在LATERAL
连接出现之前,这是一个有用的特性。现在它只是历史的压载物。
- PostgreSQL的并行unnest()和排序顺序
- 并行嵌套多个数组 在PostgreSQL中,LATERAL JOIN和子查询有什么区别?
我找不到任何相关文档。然而,我可以描述我观察到的行为。
集合生成函数每个返回一个有限行数。Postgres似乎运行集合生成函数,直到中的所有都在它们的最后一行,或者更有可能在所有都返回到它们的第一行时停止。从技术上讲,这将是系列长度的最小公倍数(LCM)。
我不知道为什么会这样。而且,正如我在评论中所说,我认为通常将函数放在from
子句中更好。
文档中只有一个关于这个问题的注释。我不确定这是否解释了所描述的行为。也许更重要的是不建议使用这样的函数:
目前,返回集合的函数也可以在查询的选择列表中调用。对于查询本身生成的每一行,将调用函数返回集,并为函数结果集的每个元素生成一个输出行。但是请注意,此功能已被弃用,并且可能在将来的版本中被删除。