本文介绍了PostgreSQL 中是否有类似 zip() 函数的东西,它结合了两个数组?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 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(数组表达式):

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() 函数的东西,它结合了两个数组?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

11-03 11:18