Zmieniłem nazwę Twojej kolumny group
do grp
ponieważ group
jest słowem zarezerwowanym
w Postgresie i każdym standardzie SQL i nie powinien być używany jako identyfikator.
Rozumiem Twoje pytanie w ten sposób:
Posortuj dwie tablice w identycznym porządku sortowania, tak aby ta sama pozycja elementu odpowiadała temu samemu wierszowi w obu tablicach.
Użyj podzapytania lub CTE i uporządkuj wiersze przed agregacją.
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;
To szybciej niż używać indywidualnego ORDER BY
klauzule w funkcji agregującej
array_agg()
jak @Mosty demonstruje
(i który istnieje od PostgreSQL 9.0). Mosty również inaczej interpretuje twoje pytanie i używa odpowiednich narzędzi do jego interpretacji.
Czy ORDER BY
w sejfie na podzapytanie?
Więc tak, w tym przykładzie jest to bezpieczne.
Bez podzapytania
Jeśli naprawdę potrzebujesz rozwiązanie bez podzapytania , możesz:
SELECT id
, array_agg(grp ORDER BY grp)
, array_agg(dt ORDER BY grp, dt)
FROM tbl
GROUP BY id;
Zwróć uwagę na ORDER BY grp, dt
. Sortuję według dt
oprócz zerwania więzi i sprawienia, aby porządek sortowania był jednoznaczny. Nie jest konieczne dla grp
jednak.
Można to zrobić również w zupełnie inny sposób, za pomocą funkcji okien :
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;
Zwróć uwagę na DISTINCT ON (id)
zamiast po prostu DISTINCT
który daje ten sam wynik, ale działa szybciej o rząd wielkości, ponieważ nie potrzebujemy dodatkowego sortowania.
Przeprowadziłem kilka testów i jest to prawie tak samo szybkie jak pozostałe dwa rozwiązania. Zgodnie z oczekiwaniami wersja podzapytania była nadal najszybsza. Przetestuj za pomocą EXPLAIN ANALYZE
aby zobaczyć na własne oczy.