PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

C'è qualcosa come una funzione zip() in PostgreSQL che combina due array?

Postgres 9.5 o successivo

ha array_agg(array expression) :

array_agg ( anyarray ) → anyarray

Concatena tutti gli array di input in un array di una dimensione superiore. (Gli input devono avere tutti la stessa dimensionalità e non possono essere vuoti o nulli.)

Questo è un sostituto rapido per la mia funzione di aggregazione personalizzata array_agg_mult() dimostrato di seguito. È implementato in C e notevolmente più veloce. Usalo.

Postgres 9.4

Usa le ROWS FROM build o l'aggiornamento unnest() che richiede più array per disnidificare in parallelo. Ognuno può avere una lunghezza diversa. Ottieni (per documentazione):

[...] il numero di righe di risultati in questo caso è quello della funzione più grande, con risultati più piccoli riempiti con valori null da abbinare.

Usa questa variante più pulita e semplice:

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

Postgres 9.3 o precedente

Zip semplice()

Considera la seguente demo per Postgres 9.3 o precedenti :

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

Risultato:

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

Tieni presente che entrambi gli array devono avere lo stesso numero di elementi per annullare l'annidamento in parallelo, oppure ottieni invece un collegamento incrociato.

Puoi racchiuderlo in una funzione, se lo desideri:

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

Chiama:

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

Stesso risultato.

zip() in array multidimensionale:

Ora, se vuoi aggregare quel nuovo insieme di array in un unico bidimensionale array, diventa più complicato.

SELECT ARRAY (SELECT ...)

oppure:

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

oppure:

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

risulteranno tutti nello stesso messaggio di errore (testato con pg 9.1.5):

ERRORE:impossibile trovare il tipo di array per il tipo di dati text[]

Ma c'è un modo per aggirare questo problema, come abbiamo risolto con questa domanda strettamente correlata.
Crea una funzione di aggregazione personalizzata:

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

E usalo in questo modo:

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

Risultato:

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

Nota l'ulteriore ARRAY[] strato! Senza di essa e solo:

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

Ottieni:

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

Che potrebbe essere utile per altri scopi.

Tira un'altra funzione:

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

Chiama:

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

Risultato:

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