PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Existe algo como uma função zip() no PostgreSQL que combina dois arrays?

Postgres 9.5 ou posterior


tem array_agg(array expression) :

array_agg ( anyarray ) → anyarray

Concatena todos os arrays de entrada em um array de uma dimensão superior. (As entradas devem ter todas a mesma dimensionalidade e não podem ser vazias ou nulas.)

Este é um substituto para minha função agregada personalizada array_agg_mult() demonstrado abaixo. É implementado em C e consideravelmente mais rápido. Use-o.

Postgres 9.4


Use o ROWS FROM construct ou o unnest() atualizado que leva vários arrays para desaninhar em paralelo. Cada um pode ter um comprimento diferente. Você obtém (por documentação):

[...] o número de linhas de resultado neste caso é o do maior resultado da função, com resultados menores preenchidos com valores nulos para corresponder.

Use esta variante mais limpa e simples:
SELECT ARRAY[a,b] AS ab
FROM   unnest('{a,b,c}'::text[] 
            , '{d,e,f}'::text[]) x(a,b);

Postgres 9.3 ou anterior

Zip simples()


Considere a seguinte demonstração do Postgres 9.3 ou anterior :
SELECT ARRAY[a,b] AS ab
FROM  (
   SELECT unnest('{a,b,c}'::text[]) AS a
        , unnest('{d,e,f}'::text[]) AS b
    ) x;

Resultado:
  ab
-------
 {a,d}
 {b,e}
 {c,f}

Observe que ambas as matrizes devem ter o mesmo número de elementos para desaninhar em paralelo ou, em vez disso, você obtém uma junção cruzada.

Você pode envolver isso em uma função, se quiser:
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$;

Ligar:
SELECT zip('{a,b,c}'::text[],'{d,e,f}'::text[]);

Mesmo resultado.

zip() para array multidimensional:


Agora, se você deseja agregar esse novo conjunto de matrizes em um bidimensional array, fica mais complicado.
SELECT ARRAY (SELECT ...)

ou:
SELECT array_agg(ARRAY[a,b]) AS ab
FROM  (
   SELECT unnest('{a,b,c}'::text[]) AS a
         ,unnest('{d,e,f}'::text[]) AS b
    ) x

ou:
SELECT array_agg(ARRAY[ARRAY[a,b]]) AS ab
FROM  ...

todos resultarão na mesma mensagem de erro (testado com a página 9.1.5):

ERRO:não foi possível encontrar o tipo de matriz para o tipo de dados text[]

Mas há uma maneira de contornar isso, pois trabalhamos nesta questão intimamente relacionada.
Crie uma função de agregação personalizada:
CREATE AGGREGATE array_agg_mult (anyarray) (
   SFUNC    = array_cat
 , STYPE    = anyarray
 , INITCOND = '{}'
);

E use assim:
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

Resultado:
{{a,d},{b,e},{c,f}}

Observe o ARRAY[] adicional camada! Sem ele e apenas:
SELECT array_agg_mult(ARRAY[a,b]) AS ab
FROM ...

Você obtém:
{a,d,b,e,c,f}

O que pode ser útil para outros fins.

Role outra função:
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$;

Ligar:
SELECT zip2('{a,b,c}'::text[],'{d,e,f}'::text[]); -- or any other array type

Resultado:
{{a,d},{b,e},{c,f}}