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

Unione di array all'interno di group by clausola

UNION ALL

Potresti "controbattere" con UNION ALL primo:

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;

Adattato per produrre l'ordine dei valori che hai richiesto in seguito. Il manuale:

Enfasi in grassetto la mia.

LATERAL sottoquery con VALUES espressione

LATERAL richiede Postgres 9.3 o successivo.

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;

Stesso risultato. Serve solo un passaggio sul tavolo.

Funzione di aggregazione personalizzata

Oppure potresti creare una funzione aggregata personalizzata come discusso in queste risposte correlate:

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

Quindi puoi:

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

Oppure, in genere più veloce, sebbene non SQL standard:

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

Il ORDER BY id aggiunto (che può essere aggiunto a tali funzioni aggregate) garantisce il risultato desiderato:

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

Oppure potresti essere interessato a questa alternativa:

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

Che produce array bidimensionali:

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

L'ultimo può essere sostituito (e dovrebbe esserlo, dato che è più veloce!) con il built-in array_agg() in Postgres 9.5 o successivo - con la sua capacità aggiuntiva di aggregare gli array:

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

Stesso risultato. Il manuale:

Quindi non è esattamente la stessa della nostra funzione di aggregazione personalizzata array_agg_mult();