Jag ändrade ditt kolumnnamn group
till grp
eftersom group
är ett reserverat ord
i Postgres och alla SQL-standarder och bör inte användas som identifierare.
Jag förstår din fråga så här:
Få de två arrayerna sorterade i identisk sorteringsordning så att samma elementposition motsvarar samma rad i båda arrayerna.
Använd en underfråga eller CTE och ordna raderna innan du aggregerar.
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 är snabbare än att använda individuella ORDER BY
satser i aggregatfunktionen
array_agg()
gillar @Mosty demonstrerar
(och som har funnits där sedan PostgreSQL 9.0). Mosty tolkar också din fråga annorlunda och använder de rätta verktygen för sin tolkning.
Är ORDER BY
i ett kassaskåp för undersökning?
Så ja, det är säkert i exemplet.
Utan underfråga
Om du verkligen behöver en lösning utan underfråga , du kan:
SELECT id
, array_agg(grp ORDER BY grp)
, array_agg(dt ORDER BY grp, dt)
FROM tbl
GROUP BY id;
Notera ORDER BY grp, dt
. Jag sorterar efter dt
förutom att bryta banden och göra sorteringsordningen entydig. Inte nödvändigt för grp
dock.
Det finns också ett helt annat sätt att göra detta, med fönsterfunktioner :
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;
Notera DISTINCT ON (id)
istället för bara DISTINCT
som ger samma resultat men presterar snabbare med en storleksordning eftersom vi inte behöver en extra sortering.
Jag körde några tester och det här är nästan lika snabbt som de andra två lösningarna. Som väntat var subquery-versionen fortfarande snabbast. Testa med EXPLAIN ANALYZE
att se själv.