Arrays 为什么这些连接会根据大小而有所不同?
在Postgresql中,如果取消嵌套两个大小相同的数组,它们会将一个数组中的每个值与另一个数组中的每个值对齐,但如果两个数组的大小不同,它会将一个数组中的每个值与另一个数组中的每个值合并Arrays 为什么这些连接会根据大小而有所不同?,arrays,postgresql,Arrays,Postgresql,在Postgresql中,如果取消嵌套两个大小相同的数组,它们会将一个数组中的每个值与另一个数组中的每个值对齐,但如果两个数组的大小不同,它会将一个数组中的每个值与另一个数组中的每个值合并 select unnest(ARRAY[1, 2, 3, 4, 5]::bigint[]) as id, unnest(ARRAY['a', 'b', 'c', 'd', 'e']) as value 会回来的 1 | "a" 2 | "b" 3 | "c" 4 | "d" 5 | "e" 1 | "a"
select unnest(ARRAY[1, 2, 3, 4, 5]::bigint[]) as id,
unnest(ARRAY['a', 'b', 'c', 'd', 'e']) as value
会回来的
1 | "a"
2 | "b"
3 | "c"
4 | "d"
5 | "e"
1 | "a"
1 | "b"
1 | "c"
1 | "d"
2 | "b"
2 | "a"
2 | "c"
2 | "d"
3 | "b"
3 | "d"
3 | "a"
3 | "c"
4 | "d"
4 | "a"
4 | "c"
4 | "b"
5 | "d"
5 | "c"
5 | "b"
5 | "a"
但是
会回来的
1 | "a"
2 | "b"
3 | "c"
4 | "d"
5 | "e"
1 | "a"
1 | "b"
1 | "c"
1 | "d"
2 | "b"
2 | "a"
2 | "c"
2 | "d"
3 | "b"
3 | "d"
3 | "a"
3 | "c"
4 | "d"
4 | "a"
4 | "c"
4 | "b"
5 | "d"
5 | "c"
5 | "b"
5 | "a"
为什么会这样?我假设正在使用某种隐式规则,我想知道我是否可以显式地这样做(例如,当我有匹配的数组大小时,我是否希望使用第二种样式,或者我是否希望将一个数组中缺少的值视为NULL)。在
SELECT
中支持集合返回函数是一个PostgreSQL扩展,而且是一个非常奇怪的扩展。人们普遍认为它已被弃用,最好尽可能避免使用
尽可能避免在-选择中使用SRF
既然9.3中支持了LATERAL
,两个主要用途之一就消失了。如果您想将一个SRF的输出用作另一个SRF的输入,则必须在SELECT
中使用设置返回功能;横向
不再需要此功能
在9.4中,当添加带有顺序性的时,另一个用法将被替换,允许您保留集合返回函数的输出顺序。这是目前剩下的主要用途:将两个SRF的输出压缩到匹配值对的行集中<对于unnest
,最需要的是带有有序性的code>,但可用于任何其他SRF
为什么会有奇怪的输出?
PostgreSQL在这里使用的逻辑(无论出于什么疯狂的原因,它最初是在古代历史中引入的)是:无论何时任一函数产生输出,都会发出一行。如果只有一个函数生成了输出,请再次扫描另一个函数的输出以获得所需的行。如果两者都不产生输出,则停止发射行
使用generate_series
更容易查看
regress=> SELECT generate_series(1,2), generate_series(1,2);
generate_series | generate_series
-----------------+-----------------
1 | 1
2 | 2
(2 rows)
regress=> SELECT generate_series(1,2), generate_series(1,3);
generate_series | generate_series
-----------------+-----------------
1 | 1
2 | 2
1 | 3
2 | 1
1 | 2
2 | 3
(6 rows)
regress=> SELECT generate_series(1,2), generate_series(1,4);
generate_series | generate_series
-----------------+-----------------
1 | 1
2 | 2
1 | 3
2 | 4
(4 rows)
在大多数情况下,您真正想要的是两者的简单交叉连接,这要明智得多
regress=> SELECT a, b FROM generate_series(1,2) a, generate_series(1,2) b;
a | b
---+---
1 | 1
1 | 2
2 | 1
2 | 2
(4 rows)
regress=> SELECT a, b FROM generate_series(1,2) a, generate_series(1,3) b;
a | b
---+---
1 | 1
1 | 2
1 | 3
2 | 1
2 | 2
2 | 3
(6 rows)
regress=> SELECT a, b FROM generate_series(1,2) a, generate_series(1,4) b;
a | b
---+---
1 | 1
1 | 2
1 | 3
1 | 4
2 | 1
2 | 2
2 | 3
2 | 4
(8 rows)
当前的主要例外情况是,当您希望在锁定步骤中成对运行多个函数时(如zip
),这是您当前无法使用联接执行的
具有顺序性
这将在9.4中通过使用
和来改进,虽然它的效率比SELECT中的多个SRF扫描要低一些(除非添加了优化器改进),但它将更加稳健
regress=> SELECT a, b FROM generate_series(1,2) a, generate_series(1,2) b;
a | b
---+---
1 | 1
1 | 2
2 | 1
2 | 2
(4 rows)
regress=> SELECT a, b FROM generate_series(1,2) a, generate_series(1,3) b;
a | b
---+---
1 | 1
1 | 2
1 | 3
2 | 1
2 | 2
2 | 3
(6 rows)
regress=> SELECT a, b FROM generate_series(1,2) a, generate_series(1,4) b;
a | b
---+---
1 | 1
1 | 2
1 | 3
1 | 4
2 | 1
2 | 2
2 | 3
2 | 4
(8 rows)
假设您想将1..3
和10..40
与多余元素的空值配对。使用带有有序性的(仅限PostgreSQL 9.4):
当来自的srf返回时:
regress=# SELECT generate_series(1,3) aval, generate_series(1,4) bval;
aval | bval
------+------
1 | 1
2 | 2
3 | 3
1 | 4
2 | 1
3 | 2
1 | 3
2 | 4
3 | 1
1 | 2
2 | 3
3 | 4
(12 rows)
值得一提的是,LATERAL
在这里是隐式的,特别是因为本例不使用其他from子句中的术语,因为LATERAL允许。另外,在添加侧向力之前,您可以将srf作为from子句,对吗?