sql >> Base de Datos >  >> RDS >> PostgreSQL

¿Hay algo como una función zip() en PostgreSQL que combine dos matrices?

Postgres 9.5 o posterior

tiene array_agg(array expression) :

array_agg ( anyarray ) → anyarray

Concatena todas las matrices de entrada en una matriz de una dimensión superior. (Todas las entradas deben tener la misma dimensionalidad y no pueden estar vacías o nulas).

Este es un reemplazo directo para mi función agregada personalizada array_agg_mult() demostrado a continuación. Está implementado en C y considerablemente más rápido. Úsalo.

Postgres 9.4

Usa las ROWS FROM construcción o el unnest() actualizado lo que requiere múltiples arreglos para anularlos en paralelo. Cada uno puede tener una longitud diferente. Obtienes (por documentación):

[...] la cantidad de filas de resultados en este caso es la del resultado de función más grande, con resultados más pequeños rellenados con valores nulos para que coincidan.

Usa esta variante más limpia y simple:

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

Postgres 9.3 o anterior

Simple zip()

Considere la siguiente demostración para Postgres 9.3 o 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}

Tenga en cuenta que ambas matrices deben tener el mismo número de elementos para anular en paralelo, o obtienes una unión cruzada en su lugar.

Puede envolver esto en una función, si desea:

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$;

Llamar:

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

Mismo resultado.

zip() a matriz multidimensional:

Ahora, si desea agregar ese nuevo conjunto de arreglos en uno bidimensional matriz, se vuelve más complicado.

SELECT ARRAY (SELECT ...)

o:

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

o:

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

todos darán como resultado el mismo mensaje de error (probado con pg 9.1.5):

ERROR:no se pudo encontrar el tipo de matriz para el tipo de datos text[]

Pero hay una forma de evitar esto, como averiguamos en esta pregunta estrechamente relacionada.
Cree una función agregada personalizada:

CREATE AGGREGATE array_agg_mult (anyarray) (
   SFUNC    = array_cat
 , STYPE    = anyarray
 , INITCOND = '{}'
);

Y úsalo así:

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}}

Tenga en cuenta el ARRAY[] adicional ¡capa! Sin él y solo:

SELECT array_agg_mult(ARRAY[a,b]) AS ab
FROM ...

obtienes:

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

Que puede ser útil para otros fines.

Tira otra función:

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$;

Llamar:

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

Resultado:

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