sql >> Database >  >> RDS >> PostgreSQL

Deelnemen aan arrays binnen groep op clausule

UNION ALL

Je zou kunnen "tegendraaien" met UNION ALL eerst:

SELECT name, array_agg(c) AS c_arr
FROM  (
   SELECT name, id, 1 AS rnk, col1 AS c FROM tbl
   UNION ALL
   SELECT name, id, 2, col2 FROM tbl
   ORDER  BY name, id, rnk
   ) sub
GROUP  BY 1;

Aangepast om de volgorde van waarden te produceren die u later hebt aangevraagd. De handleiding:

Vetgedrukte nadruk van mij.

LATERAL subquery met VALUES uitdrukking

LATERAL vereist Postgres 9.3 of later.

SELECT t.name, array_agg(c) AS c_arr
FROM  (SELECT * FROM tbl ORDER BY name, id) t
CROSS  JOIN LATERAL (VALUES (t.col1), (t.col2)) v(c)
GROUP  BY 1;

Zelfde resultaat. Heeft maar een enkele pas over de tafel nodig.

Aangepaste aggregatiefunctie

Of je zou een aangepaste aggregatiefunctie kunnen maken zoals besproken in deze gerelateerde antwoorden:

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

Dan kun je:

SELECT name, array_agg_mult(ARRAY[col1, col2] ORDER BY id) AS c_arr
FROM   tbl
GROUP  BY 1
ORDER  BY 1;

Of, meestal sneller, hoewel niet standaard SQL:

SELECT name, array_agg_mult(ARRAY[col1, col2]) AS c_arr
FROM  (SELECT * FROM tbl ORDER BY name, id) t
GROUP  BY 1;

De toegevoegde ORDER BY id (die aan dergelijke geaggregeerde functies kan worden toegevoegd) garandeert het gewenste resultaat:

a | {1,2,3,4}
b | {5,6,7,8}

Of misschien ben je geïnteresseerd in dit alternatief:

SELECT name, array_agg_mult(ARRAY[ARRAY[col1, col2]] ORDER BY id) AS c_arr
FROM   tbl
GROUP  BY 1
ORDER  BY 1;

Die 2-dimensionale arrays produceert:

a | {{1,2},{3,4}}
b | {{5,6},{7,8}}

De laatste kan worden vervangen (en zou moeten zijn, want het is sneller!) met de ingebouwde array_agg() in Postgres 9.5 of later - met de toegevoegde mogelijkheid om arrays te aggregeren:

SELECT name, array_agg(ARRAY[col1, col2] ORDER BY id) AS c_arr
FROM   tbl
GROUP  BY 1
ORDER  BY 1;

Zelfde resultaat. De handleiding:

Dus niet precies hetzelfde als onze aangepaste aggregatiefunctie array_agg_mult();



  1. MySQL UPDATE voeg gegevens toe aan kolom

  2. Hoe InnoDB op te lossen:Kan ./ibdata1 mysql-fout niet vergrendelen?

  3. SQLiteOpenHelper:methode onCreate() niet aangeroepen op fysiek apparaat

  4. Update-instructie loopt te lang of niet