Jeg har ændret dit kolonnenavn group
til grp
fordi group
er et reserveret ord
i Postgres og enhver SQL-standard og bør ikke bruges som identifikator.
Jeg forstår dit spørgsmål sådan her:
Få de to arrays sorteret i identisk sorteringsrækkefølge, så den samme elementposition svarer til den samme række i begge arrays.
Brug en underforespørgsel eller CTE og bestil rækkerne, før du samler.
SELECT id, array_agg(grp) AS grp, array_agg(dt) AS dt
FROM (
SELECT *
FROM tbl
ORDER BY id, grp, dt
) x
GROUP BY id;
Det er hurtigere end at bruge individuelle ORDER BY
klausuler i den samlede funktion
array_agg()
synes godt om @Mosty demonstrerer
(og som har været der siden PostgreSQL 9.0). Mosty fortolker også dit spørgsmål anderledes og bruger de rigtige værktøjer til sin fortolkning.
Er ORDER BY
i et underforespørgselsskab?
Så ja, det er sikkert i eksemplet.
Uden underforespørgsel
Hvis du virkelig bruger en løsning uden underforespørgsel , kan du:
SELECT id
, array_agg(grp ORDER BY grp)
, array_agg(dt ORDER BY grp, dt)
FROM tbl
GROUP BY id;
Bemærk ORDER BY grp, dt
. Jeg sorterer efter dt
ud over at bryde bånd og gøre sorteringsrækkefølgen entydig. Ikke nødvendigt for grp
dog.
Der er også en helt anden måde at gøre dette på, med vinduefunktioner :
SELECT DISTINCT ON (id)
id
, array_agg(grp) OVER w AS grp
, array_agg(dt) OVER w AS dt
FROM tbl
WINDOW w AS (PARTITION BY id ORDER BY grp, dt
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)
ORDER BY id;
Bemærk DISTINCT ON (id)
i stedet for blot DISTINCT
som giver det samme resultat, men klarer sig hurtigere i en størrelsesorden, fordi vi ikke har brug for en ekstra sortering.
Jeg kørte nogle tests, og dette er næsten lige så hurtigt som de to andre løsninger. Som forventet var underforespørgselsversionen stadig hurtigst. Test med EXPLAIN ANALYZE
at se selv.