Ich habe Ihren Spaltennamen group
geändert zu grp
weil group
ist ein reserviertes Wort
in Postgres und jedem SQL-Standard und sollte nicht als Bezeichner verwendet werden.
Ich verstehe Ihre Frage so:
Sortieren Sie die beiden Arrays in identischer Sortierreihenfolge, sodass dieselbe Elementposition derselben Zeile in beiden Arrays entspricht.
Verwenden Sie eine Unterabfrage oder CTE und sortieren Sie die Zeilen, bevor Sie aggregieren.
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;
Das ist schneller als einzelne ORDER BY
zu verwenden Klauseln in der Aggregatfunktion
array_agg()
wie @Mosty demonstriert
(und die es seit PostgreSQL 9.0 gibt). Mosty interpretiert Ihre Frage auch anders und verwendet die richtigen Werkzeuge für seine Interpretation.
Ist ORDER BY
in einer Unterabfrage sicher?
Also ja, im Beispiel ist es sicher.
Ohne Unterabfrage
Wenn Sie wirklich brauchen eine Lösung ohne Unterabfrage , können Sie:
SELECT id
, array_agg(grp ORDER BY grp)
, array_agg(dt ORDER BY grp, dt)
FROM tbl
GROUP BY id;
Beachten Sie den ORDER BY grp, dt
. Ich sortiere nach dt
zusätzlich dazu, Bindungen zu lösen und die Sortierreihenfolge eindeutig zu machen. Nicht notwendig für grp
, obwohl.
Es gibt auch einen ganz anderen Weg, dies zu tun, mit Fensterfunktionen :
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;
Beachten Sie den DISTINCT ON (id)
statt nur DISTINCT
die das gleiche Ergebnis liefert, aber um eine Größenordnung schneller arbeitet, weil wir keine zusätzliche Sortierung benötigen.
Ich habe einige Tests durchgeführt und das ist fast so schnell wie die anderen beiden Lösungen. Wie erwartet war die Subquery-Version immer noch am schnellsten. Testen Sie mit EXPLAIN ANALYZE
um es selbst zu sehen.