sql >> Databasteknik >  >> RDS >> PostgreSQL

Finns det något som en zip()-funktion i PostgreSQL som kombinerar två arrayer?

Postgres 9.5 eller senare

har array_agg(array expression) :

array_agg ( anyarray ) → anyarray

Sammanfogar alla inmatningsmatriser till en matris med en högre dimension. (Ingångarna måste alla ha samma dimensionalitet och får inte vara tomma eller noll.)

Detta är en drop-in-ersättning för min anpassade aggregatfunktion array_agg_mult() visas nedan. Det är implementerat i C och betydligt snabbare. Använd den.

Postgres 9.4

Använd ROWS FROM konstruktion eller den uppdaterade unnest() vilket tar flera arrayer för att unnestra parallellt. Var och en kan ha olika längd. Du får (per dokumentation):

[...] antalet resultatrader i det här fallet är det största funktionsresultatet, med mindre resultat fyllda med nollvärden för att matcha.

Använd denna renare och enklare 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

Enkel zip()

Överväg följande demo för Postgres 9.3 eller tidigare :

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}

Observera att båda arrayerna måste ha samma antal element att odla parallellt, eller så får du en tvärfog istället.

Du kan slå in detta i en funktion om du vill:

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:

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

Samma resultat.

zip() till flerdimensionell array:

Om du nu vill samla den nya uppsättningen arrayer i en 2-dimensionell array blir det mer komplicerat.

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

kommer alla att resultera i samma felmeddelande (testat med sid 9.1.5):

FEL:kunde inte hitta matristyp för datatyptext[]

Men det finns en väg runt detta, som vi utarbetade under denna närbesläktade fråga.
Skapa en anpassad aggregatfunktion:

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

Och använd det så här:

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

Notera den extra ARRAY[] lager! Utan det och bara:

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

Du får:

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

Vilket kan vara användbart för andra ändamål.

Rulla en annan 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:

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

Resultat:

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


  1. WEEKOFYEAR() Exempel – MySQL

  2. MariaDB JSON_CONTAINS_PATH() Förklarad

  3. Hur RPAD() fungerar i MariaDB

  4. pgAdmin III Varför förkortas frågeresultat?