W PostgreSQL możemy użyć STRING_AGG()
funkcja zwracająca kolumny z zapytania w postaci rozdzielanej listy.
Składnia
Składnia wygląda tak:
string_agg ( value text, delimiter text ) → text
string_agg ( value bytea, delimiter bytea ) → bytea
Możemy również użyć ORDER BY
klauzula i DISTINCT
klauzula z tej funkcji, która wpływa na dane wyjściowe funkcji. Więcej na ten temat poniżej.
Przykład
Załóżmy, że uruchamiamy następujące zapytanie:
SELECT PetName
FROM Pets;
I otrzymujemy następujący wynik:
+---------+ | petname | +---------+ | Fluffy | | Fetch | | Scratch | | Wag | | Tweet | | Fluffy | | Bark | | Meow | +---------+ (8 rows)
Możemy użyć STRING_AGG()
aby zwrócić wszystkie te wiersze jako listę rozdzielaną.
Aby to zrobić, przekaż PetName
kolumna jako pierwszy argument i wybrany przez nas ogranicznik jako drugi argument:
SELECT STRING_AGG(PetName, ',')
FROM Pets;
Wynik:
+-------------------------------------------------+ | string_agg | +-------------------------------------------------+ | Fluffy,Fetch,Scratch,Wag,Tweet,Fluffy,Bark,Meow | +-------------------------------------------------+ (1 row)
Zmiana ogranicznika
W poprzednim przykładzie jako ogranicznik wybrałem przecinek. Tutaj jest z innym ogranicznikiem:
SELECT STRING_AGG(PetName, '-')
FROM Pets;
Wynik:
Fluffy-Fetch-Scratch-Wag-Tweet-Fluffy-Bark-Meow
Możemy nawet użyć pustego ciągu, aby usunąć wszystkie separatory (aby wartości były połączone):
SELECT STRING_AGG(PetName, '')
FROM Pets;
I otrzymujemy następujący wynik:
FluffyFetchScratchWagTweetFluffyBarkMeow
Zamawianie
Możemy użyć ORDER BY
klauzula w STRING_AGG()
funkcja zamawiania własnego wyjścia:
SELECT STRING_AGG(PetName, ',' ORDER BY PetName ASC) FROM Pets;
Wynik:
Bark,Fetch,Fluffy,Fluffy,Meow,Scratch,Tweet,Wag
To było w porządku rosnącym.
Oto w porządku malejącym:
SELECT STRING_AGG(PetName, ',' ORDER BY PetName DESC) FROM Pets;
Wynik:
Wag,Tweet,Scratch,Meow,Fluffy,Fluffy,Fetch,Bark
Zauważ, że to sortuje tylko dane wyjściowe STRING_AGG()
funkcja – jest całkowicie niezależna od dowolnej kolejności zastosowanej do SELECT
samo oświadczenie.
DISTINCT
Klauzula
Możemy użyć DISTINCT
klauzula zwracająca unikalne wartości. Innymi słowy, jeśli istnieją zduplikowane wartości, zwracane jest tylko jedno wystąpienie:
SELECT STRING_AGG(DISTINCT PetName, ',' ORDER BY PetName ASC) FROM Pets;
Wynik:
Bark,Fetch,Fluffy,Meow,Scratch,Tweet,Wag
W tym przypadku Fluffy
pojawia się tylko raz. Kiedy uruchamiamy go bez DISTINCT
klauzula, Fluffy
pojawia się dwukrotnie:
SELECT STRING_AGG(PetName, ',' ORDER BY PetName ASC) FROM Pets;
Wynik:
Bark,Fetch,Fluffy,Fluffy,Meow,Scratch,Tweet,Wag
Zgrupowane wyniki zapytań
Możemy dołączyć STRING_AGG()
w zapytaniu z GROUP BY
klauzula, aby osiągnąć taki wynik:
SELECT
PetTypeId,
STRING_AGG(PetName, ',' ORDER BY PetName ASC)
FROM Pets
GROUP BY PetTypeId
ORDER BY PetTypeId;
Wynik:
+-----------+-----------------------+ | pettypeid | string_agg | +-----------+-----------------------+ | 1 | Tweet | | 2 | Fluffy,Meow,Scratch | | 3 | Bark,Fetch,Fluffy,Wag | +-----------+-----------------------+
W mojej bazie danych rzeczywiste nazwy typów zwierząt znajdują się w innej tabeli o nazwie PetTypes
. Mogliśmy zatem uruchomić INNER JOIN
w PetTypes
tabela, aby uzyskać rzeczywiste nazwy typów zwierząt:
SELECT
pt.PetType,
STRING_AGG(p.PetName, ',' ORDER BY p.PetName ASC)
FROM Pets p
INNER JOIN PetTypes pt ON
p.PetTypeId = pt.PetTypeId
GROUP BY pt.PetType
ORDER BY pt.PetType ASC;
Wynik:
+---------+-----------------------+ | pettype | string_agg | +---------+-----------------------+ | Bird | Tweet | | Cat | Fluffy,Meow,Scratch | | Dog | Bark,Fetch,Fluffy,Wag | +---------+-----------------------+