Промених името на колоната ви group
към grp
защото group
е запазена дума
в Postgres и всеки SQL стандарт и не трябва да се използва като идентификатор.
Разбирам въпроса ви така:
Сортирайте двата масива в идентичен ред на сортиране, така че една и съща позиция на елемента да съответства на един и същ ред и в двата масива.
Използване на подзаявка или CTE и подредете редовете, преди да обобщите.
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;
Това е по-бързо отколкото да използвате индивидуален ORDER BY
клаузи в агрегатната функция
array_agg()
като @Mosty демонстрира
(и който е там от PostgreSQL 9.0). Мости също тълкува въпроса ви по различен начин и използва правилните инструменти за своето тълкуване.
Е ORDER BY
в сейф на подзаявка?
Така че да, в примера е безопасно.
Без подзаявка
Ако наистина имате нужда решение без подзаявка , можете да:
SELECT id
, array_agg(grp ORDER BY grp)
, array_agg(dt ORDER BY grp, dt)
FROM tbl
GROUP BY id;
Обърнете внимание на ORDER BY grp, dt
. Сортирам по dt
в допълнение към прекъсване на връзките и недвусмислен ред на сортиране. Не е необходимо за grp
, обаче.
Има и напълно различен начин да направите това, с прозоречни функции :
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;
Обърнете внимание на DISTINCT ON (id)
вместо само DISTINCT
което дава същия резултат, но работи по-бързо с порядък, защото не се нуждаем от допълнително сортиране.
Проведох няколко теста и това е почти толкова бързо, колкото другите две решения. Както се очакваше, версията на подзаявката все още беше най-бърза. Тествайте с EXPLAIN ANALYZE
за да видите сами.