Ik heb je kolomnaam group
gewijzigd naar grp
omdat group
is een gereserveerd woord
in Postgres en elke SQL-standaard en mag niet als identifier worden gebruikt.
Ik begrijp uw vraag als volgt:
Laat de twee arrays in identieke sorteervolgorde sorteren, zodat dezelfde elementpositie overeenkomt met dezelfde rij in beide arrays.
Gebruik een subquery of CTE en rangschik de rijen voordat u aggregeert.
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;
Dat is sneller dan om individuele ORDER BY
te gebruiken clausules in de aggregatiefunctie
array_agg()
like @Mosty demonstreert
(en die er al is sinds PostgreSQL 9.0). Mosty interpreteert je vraag ook anders en gebruikt de juiste tools voor zijn interpretatie.
Is ORDER BY
in een subquery-kluis?
Dus ja, in het voorbeeld is het veilig.
Zonder subquery
Als je echt nodig een oplossing zonder subquery , kunt u:
SELECT id
, array_agg(grp ORDER BY grp)
, array_agg(dt ORDER BY grp, dt)
FROM tbl
GROUP BY id;
Let op de ORDER BY grp, dt
. Ik sorteer op dt
naast het verbreken van banden en het eenduidig maken van de sorteervolgorde. Niet nodig voor grp
, hoewel.
Er is ook een heel andere manier om dit te doen, met vensterfuncties :
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;
Let op de DISTINCT ON (id)
in plaats van alleen DISTINCT
wat hetzelfde resultaat oplevert maar een orde van grootte sneller presteert omdat we geen extra sortering nodig hebben.
Ik heb wat tests uitgevoerd en dit is bijna net zo snel als de andere twee oplossingen. Zoals verwacht was de subqueryversie nog steeds het snelst. Test met EXPLAIN ANALYZE
om het zelf te zien.