sql >> Database >  >> RDS >> PostgreSQL

Is er zoiets als een zip()-functie in PostgreSQL die twee arrays combineert?

Postgres 9.5 of hoger

heeft array_agg(array expression) :

array_agg ( anyarray ) → anyarray

Voegt alle invoerarrays samen tot een array van één hogere dimensie. (De ingangen moeten allemaal dezelfde dimensionaliteit hebben en mogen niet leeg of nul zijn.)

Dit is een drop-in vervanging voor mijn aangepaste aggregatiefunctie array_agg_mult() hieronder aangetoond. Het is geïmplementeerd in C en aanzienlijk sneller. Gebruik het.

Postgres 9,4

Gebruik de ROWS FROM construct of de bijgewerkte unnest() die meerdere arrays nodig heeft om parallel te unnesten. Elk kan een andere lengte hebben. Je krijgt (per documentatie):

[...] het aantal resultaatrijen is in dit geval dat van het grootste functieresultaat, met kleinere resultaten opgevuld met overeenkomende null-waarden.

Gebruik deze schonere en eenvoudigere variant:

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

Postgres 9.3 of ouder

Eenvoudige zip()

Overweeg de volgende demo voor Postgres 9.3 of eerder :

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

Resultaat:

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

Merk op dat beide arrays het hetzelfde aantal elementen . moeten hebben om parallel te unnesten, of je krijgt in plaats daarvan een cross join.

Je kunt dit in een functie inpakken, als je dat wilt:

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

Bel:

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

Zelfde resultaat.

zip() naar multidimensionale array:

Als u nu wilt aggregeren die nieuwe reeks arrays in één 2-dimensionaal array, wordt het ingewikkelder.

SELECT ARRAY (SELECT ...)

of:

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

of:

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

zullen allemaal dezelfde foutmelding geven (getest met pag. 9.1.5):

FOUT:kan arraytype niet vinden voor datatype tekst[]

Maar er is een manier om dit te omzeilen, zoals we hebben uitgewerkt onder deze nauw verwante vraag.
Maak een aangepaste aggregatiefunctie:

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

En gebruik het als volgt:

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

Resultaat:

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

Let op de extra ARRAY[] laag! Zonder en gewoon:

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

Je krijgt:

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

Wat ook handig kan zijn voor andere doeleinden.

Rol een andere functie:

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

Bel:

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

Resultaat:

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


  1. MySQL-prestaties:lange zoekopdrachten identificeren

  2. Lange strings in N-Hibernate met Oracle veroorzaken fout

  3. Mysqladmin flush-hosts uitvoeren op Amazon RDS

  4. Proberen eigendom van niet-object in te krijgen