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

Er der noget som en zip() funktion i PostgreSQL, der kombinerer to arrays?

Postgres 9.5 eller nyere

har array_agg(array expression) :

array_agg ( anyarray ) → anyarray

Sammenkæder alle input-arrays til et array med én højere dimension. (Indgangene skal alle have samme dimensionalitet og må ikke være tomme eller nul.)

Dette er en drop-in-erstatning for min tilpassede aggregerede funktion array_agg_mult() vist nedenfor. Det er implementeret i C og betydeligt hurtigere. Brug det.

Postgres 9.4

Brug ROWS FROM konstruktion eller den opdaterede unnest() hvilket kræver flere arrays at unnest parallelt. Hver kan have forskellig længde. Du får (pr. dokumentation):

[...] antallet af resultatrækker i dette tilfælde er det største funktionsresultat, med mindre resultater udfyldt med nulværdier, der skal matche.

Brug denne renere og enklere variant:

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

Postgres 9.3 eller ældre

Simpel zip()

Overvej følgende demo til Postgres 9.3 eller tidligere :

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

Resultat:

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

Bemærk, at begge arrays skal have det samme antal elementer at unnest parallelt, eller du får i stedet en krydssammenføjning.

Du kan pakke dette ind i en funktion, hvis du vil:

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

Ring til:

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

Samme resultat.

zip() til multidimensional matrix:

Hvis du nu vil samle det nye sæt af arrays i én 2-dimensionel array, bliver det mere kompliceret.

SELECT ARRAY (SELECT ...) 

eller:

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 

eller:

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

vil alle resultere i den samme fejlmeddelelse (testet med side 9.1.5):

FEJL:kunne ikke finde matrixtype for datatypetekst[]

Men der er en vej rundt om dette, som vi har udarbejdet under dette nært beslægtede spørgsmål.
Opret en tilpasset aggregeret funktion:

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

Og brug det sådan her:

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
 

Resultat:

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

Bemærk den ekstra ARRAY[] lag! Uden det og bare:

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

Du får:

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

Hvilket kan være nyttigt til andre formål.

Rul en anden funktion:

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

Ring til:

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

Resultat:

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


  1. Find overtrædelser af fremmednøgler i SQLite

  2. Mysql fejl 1452 - Kan ikke tilføje eller opdatere en underordnet række:en fremmednøgle begrænsning mislykkes

  3. Kaldnotation for PL/SQL-underrutiner i Oracle-databasen

  4. Returner rækker, der matcher elementer af input-array i plpgsql-funktionen