No PostgreSQL, podemos usar o
STRING_AGG()
função para retornar colunas de uma consulta como uma lista delimitada. Sintaxe
A sintaxe fica assim:
string_agg ( value text, delimiter text ) → text
string_agg ( value bytea, delimiter bytea ) → bytea
Também podemos usar o
ORDER BY
cláusula e um DISTINCT
cláusula de dentro desta função, que afeta a saída da função. Mais sobre isso abaixo. Exemplo
Suponha que executemos a seguinte consulta:
SELECT PetName
FROM Pets;
E obtemos o seguinte resultado:
+---------+ | petname | +---------+ | Fluffy | | Fetch | | Scratch | | Wag | | Tweet | | Fluffy | | Bark | | Meow | +---------+ (8 rows)
Podemos usar
STRING_AGG()
para retornar todas essas linhas como uma lista delimitada. Para fazer isso, passe o
PetName
column como o primeiro argumento e nosso delimitador escolhido como o segundo argumento:SELECT STRING_AGG(PetName, ',')
FROM Pets;
Resultado:
+-------------------------------------------------+ | string_agg | +-------------------------------------------------+ | Fluffy,Fetch,Scratch,Wag,Tweet,Fluffy,Bark,Meow | +-------------------------------------------------+ (1 row)
Alterando o delimitador
No exemplo anterior, escolhi uma vírgula como delimitador. Aqui está com um delimitador diferente:
SELECT STRING_AGG(PetName, '-')
FROM Pets;
Resultado:
Fluffy-Fetch-Scratch-Wag-Tweet-Fluffy-Bark-Meow
Podemos até usar uma string vazia para remover todos os separadores (para que os valores sejam concatenados):
SELECT STRING_AGG(PetName, '')
FROM Pets;
E obtemos o seguinte resultado:
FluffyFetchScratchWagTweetFluffyBarkMeow
Pedidos
Podemos usar o
ORDER BY
cláusula dentro do STRING_AGG()
função para ordenar sua própria saída:SELECT STRING_AGG(PetName, ',' ORDER BY PetName ASC) FROM Pets;
Resultado:
Bark,Fetch,Fluffy,Fluffy,Meow,Scratch,Tweet,Wag
Isso foi em ordem crescente.
Aqui está em ordem decrescente:
SELECT STRING_AGG(PetName, ',' ORDER BY PetName DESC) FROM Pets;
Resultado:
Wag,Tweet,Scratch,Meow,Fluffy,Fluffy,Fetch,Bark
Observe que isso apenas classifica a saída do
STRING_AGG()
função – é completamente independente de qualquer ordenação aplicada ao SELECT
própria declaração. O DISTINCT
Cláusula
Podemos usar o
DISTINCT
cláusula para retornar valores exclusivos. Em outras palavras, se houver valores duplicados, apenas uma ocorrência será retornada:SELECT STRING_AGG(DISTINCT PetName, ',' ORDER BY PetName ASC) FROM Pets;
Resultado:
Bark,Fetch,Fluffy,Meow,Scratch,Tweet,Wag
Neste caso,
Fluffy
só aparece uma vez. Quando o executamos sem o DISTINCT
cláusula, Fluffy
aparece duas vezes:SELECT STRING_AGG(PetName, ',' ORDER BY PetName ASC) FROM Pets;
Resultado:
Bark,Fetch,Fluffy,Fluffy,Meow,Scratch,Tweet,Wag
Resultados da consulta agrupada
Podemos incluir
STRING_AGG()
em uma consulta com um GROUP BY
cláusula para obter um resultado como este:SELECT
PetTypeId,
STRING_AGG(PetName, ',' ORDER BY PetName ASC)
FROM Pets
GROUP BY PetTypeId
ORDER BY PetTypeId;
Resultado:
+-----------+-----------------------+ | pettypeid | string_agg | +-----------+-----------------------+ | 1 | Tweet | | 2 | Fluffy,Meow,Scratch | | 3 | Bark,Fetch,Fluffy,Wag | +-----------+-----------------------+
No meu banco de dados, os nomes reais dos tipos de animais de estimação estão em outra tabela chamada
PetTypes
. Portanto, poderíamos executar um INNER JOIN
nos PetTypes
table para obter os nomes reais dos tipos de animais de estimação: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;
Resultado:
+---------+-----------------------+ | pettype | string_agg | +---------+-----------------------+ | Bird | Tweet | | Cat | Fluffy,Meow,Scratch | | Dog | Bark,Fetch,Fluffy,Wag | +---------+-----------------------+