Kolejność PostgreSQL array_agg

108

„Zwierzęta” stołowe:

animal_name animal_type
Tom         Cat
Jerry       Mouse
Kermit      Frog

Pytanie:

SELECT 
array_to_string(array_agg(animal_name),';') animal_names,
array_to_string(array_agg(animal_type),';') animal_types
FROM animals;

Spodziewany wynik:

Tom;Jerry;Kerimt, Cat;Mouse;Frog
OR
Tom;Kerimt;Jerry, Cat;Frog;Mouse

Czy mogę mieć pewność, że kolejność w pierwszej funkcji agregującej będzie zawsze taka sama jak w drugiej. To znaczy nie chciałbym dostać:

Tom;Jerry;Kermit, Frog;Mouse,Cat
Olo
źródło
7
Jeśli korzystasz z wersji 9.0, możesz zastąpić zagnieżdżone wywołania pojedynczymstring_agg()
a_horse_with_no_name

Odpowiedzi:

27

Jeśli używasz PostgreSQL w wersji <9.0, to:

Od: http://www.postgresql.org/docs/8.4/static/functions-aggregate.html

W obecnej implementacji kolejność wprowadzania danych jest w zasadzie nieokreślona. Jednak podanie wartości wejściowych z posortowanego podzapytania zwykle działa. Na przykład:

SELECT xmlagg (x) FROM (SELECT x FROM test ORDER BY y DESC) AS tab;

Więc w twoim przypadku napisałbyś:

SELECT
array_to_string(array_agg(animal_name),';') animal_names,
array_to_string(array_agg(animal_type),';') animal_types
FROM (SELECT animal_name, animal_type FROM animals) AS x;

Dane wejściowe do array_agg byłyby wówczas nieuporządkowane, ale byłyby takie same w obu kolumnach. A jeśli chcesz, możesz dodać ORDER BYklauzulę do podzapytania.

UlfR
źródło
336

Użyj ORDER BY, jak w tym przykładzie z instrukcji :

SELECT array_agg(a ORDER BY b DESC) FROM table;
Frank Heikens
źródło
42
Uwaga: ORDER BYw array_aggwprowadzany jest w PostgreSQL 9
UlfR
6
Znacznie lepiej niż przyjęta odpowiedź przy założeniu PostgreSQL 9+.
Erik,
1
Czy mógłbyś podać próbkę z poleceniem ORDER BY do wyboru: SELECT array_agg (nazwa_zwierza), tablica_agg (typ_zwierza) ze zwierząt; ?
Grigorij Kislin
10
Zauważ, że to nie działa dlaarray_agg(DISTINCT a ORDER BY b)
cerd
1
Używając dla wielu kolumn, musisz dodać nawiasy:array_agg((a, b, c) ORDER BY b)
bennos