问题描述
我在 PostgreSQL 中有两个长度相同的数组值:
I have two array values of the same length in PostgreSQL:
{a,b,c}
和 {d,e,f}
我想把它们组合成
{{a,d},{b,e},{c,f}}
有没有办法做到这一点?
Is there a way to do that?
推荐答案
Postgres 9.5 或更高版本
array_agg
( anyarray
) → anyarray
将所有输入数组连接成一个更高的数组尺寸.(输入必须都具有相同的维度,并且不能为空或为空.)
Concatenates all the input arrays into an array of one higherdimension. (The inputs must all have the same dimensionality, andcannot be empty or null.)
这是我的自定义聚合函数 array_agg_mult()
的直接替代品,如下所示.它是用 C 实现的,而且速度要快得多.使用它.
This is a drop-in replacement for my custom aggregate function array_agg_mult()
demonstrated below. It's implemented in C and considerably faster. Use it.
使用 ROWS FROM
构造或更新的 unnest()
,它可以并行取消嵌套多个数组.每个可以有不同的长度.你得到(每个文档):
Use the ROWS FROM
construct or the updated unnest()
which takes multiple arrays to unnest in parallel. Each can have a different length. You get (per documentation):
[...] 这种情况下的结果行数是最大函数的行数结果,较小的结果用空值填充以匹配.
使用这个更简洁更简单的变体:
Use this cleaner and simpler variant:
SELECT ARRAY[a,b] AS ab
FROM unnest('{a,b,c}'::text[]
, '{d,e,f}'::text[]) x(a,b);
Postgres 9.3 或更早版本
简单的 zip()
考虑以下 Postgres 9.3 或更早版本的演示:
SELECT ARRAY[a,b] AS ab
FROM (
SELECT unnest('{a,b,c}'::text[]) AS a
, unnest('{d,e,f}'::text[]) AS b
) x;
结果:
ab
-------
{a,d}
{b,e}
{c,f}
请注意,两个数组必须具有相同数量的元素才能并行取消嵌套,否则您会得到一个交叉连接.
Note that both arrays must have the same number of elements to unnest in parallel, or you get a cross join instead.
如果你愿意,你可以把它包装成一个函数:
You can wrap this into a function, if you want to:
CREATE OR REPLACE FUNCTION zip(anyarray, anyarray)
RETURNS SETOF anyarray LANGUAGE SQL AS
$func$
SELECT ARRAY[a,b] FROM (SELECT unnest($1) AS a, unnest($2) AS b) x;
$func$;
调用:
SELECT zip('{a,b,c}'::text[],'{d,e,f}'::text[]);
同样的结果.
现在,如果您想将这组新数组聚合到一个二维数组中,它会变得更加复杂.
Now, if you want to aggregate that new set of arrays into one 2-dimenstional array, it gets more complicated.
或:
或:
都将导致相同的错误消息(使用 pg 9.1.5 测试):
will all result in the same error message (tested with pg 9.1.5):
错误:找不到数据类型 text[] 的数组类型
但有一种方法可以解决这个问题,正如我们在这个密切相关的问题下制定的那样.
创建自定义聚合函数:
But there is a way around this, as we worked out under this closely related question.
Create a custom aggregate function:
CREATE AGGREGATE array_agg_mult (anyarray) (
SFUNC = array_cat
, STYPE = anyarray
, INITCOND = '{}'
);
并像这样使用它:
SELECT array_agg_mult(ARRAY[ARRAY[a,b]]) AS ab
FROM (
SELECT unnest('{a,b,c}'::text[]) AS a
, unnest('{d,e,f}'::text[]) AS b
) x
结果:
{{a,d},{b,e},{c,f}}
注意附加的 ARRAY[]
层!没有它,只是:
Note the additional ARRAY[]
layer! Without it and just:
SELECT array_agg_mult(ARRAY[a,b]) AS ab
FROM ...
你得到:
{a,d,b,e,c,f}
这可能对其他目的有用.
Which may be useful for other purposes.
滚动另一个函数:
CREATE OR REPLACE FUNCTION zip2(anyarray, anyarray)
RETURNS SETOF anyarray LANGUAGE SQL AS
$func$
SELECT array_agg_mult(ARRAY[ARRAY[a,b]])
FROM (SELECT unnest($1) AS a, unnest($2) AS b) x;
$func$;
调用:
SELECT zip2('{a,b,c}'::text[],'{d,e,f}'::text[]); -- or any other array type
结果:
{{a,d},{b,e},{c,f}}
这篇关于PostgreSQL 中是否有类似 zip() 函数的东西,它结合了两个数组?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!