Usando STRING_AGG para Resultados Concisos de Consulta

A função string_agg em SQL é uma função de agregação que concatena (une) strings de várias linhas em uma única string com várias opções.

É particularmente útil quando você deseja combinar valores de uma coluna para cada grupo de dados em seus relatórios, e pode tornar o resultado da sua consulta mais fácil de ler, especialmente ao lidar com relacionamentos muitos para muitos. Por exemplo, se você quiser criar um relatório que mostre todas as tags usadas em cada tópico, você pode usar string_agg para concatenar todas as tags de cada tópico em uma única string.

Sintaxe

Aqui está a sintaxe básica de string_agg:

STRING_AGG(expression, delimiter)

A função string_agg aceita dois parâmetros:

  • expression: O valor a ser concatenado.
  • delimiter: O delimitador a ser inserido entre as strings. O delimitador pode ser uma string ou um caractere.

Exemplo de Uso em Consultas DE

Vamos dar uma olhada em alguns exemplos de consultas que utilizam string_agg

Listar Todas as Categorias em um Site

Esta consulta concatena os campos name e id da tabela categories em uma única string, com cada par name e id separado por ’ : ', e cada par separado por ', '. Os pares são então ordenados por id.

SELECT  
    -- A função STRING_AGG concatena os campos 'name' e 'id' em uma única string.
    -- Cada par 'name' e 'id' é separado por ' : ', e cada par é separado por ', '.
    -- Os pares são ordenados por 'id'.
    STRING_AGG(name || ' : ' || id, ', ' ORDER BY id) AS category_list
FROM 
    categories -- Os dados são selecionados da tabela 'categories'.

Exemplo de Resultados:

category_list
Uncategorized : 1, Site Feedback : 2, Staff : 3, Lounge : 4, Email : 5, Event : 6, Parent Category : 7, Sub Category

Listar todos os Tópicos e Tags Associadas

Esta consulta seleciona o id da tabela topics e concatena as tags associadas para cada tópico em uma única string. Cada tag é separada por uma vírgula e um espaço, e as tags são ordenadas alfabeticamente. O resultado é agrupado pelo id do tópico e ordenado pelas tags. Se um tópico não tiver tags, a coluna tags será NULL

SELECT t.id topic_id,
    string_agg(tags.name, ', ' ORDER BY tags.name) AS "tags"
FROM topics t
LEFT JOIN topic_tags tt ON tt.topic_id = t.id
LEFT JOIN tags ON tags.id = tt.tag_id
GROUP BY t.id   
ORDER BY tags

O resultado será uma lista de IDs de tópicos formatados, cada um com uma string de tags associadas ordenadas alfabeticamente. Por exemplo:

Exemplo de Resultados:

topic tags
Welcome to the Lounge (3) tag1, tag2
A Very Safe for work post (3) tag3, tag4, tag,5
This is a blog tagged post (4) tag3
About the Lounge category (3) tag5
Welcome to your 14 day standard hosting trial! NULL
Explicação Detalhada com Comentários Inline
-- Esta instrução SQL está selecionando dados da tabela 'topics' e 'tags' associadas.
SELECT 
    t.id topic_id, -- Seleciona o 'id' da tabela 'topics'.
    -- A função STRING_AGG concatena as 'tags' associadas para cada tópico em uma única string.
    -- Cada tag é separada por uma vírgula e um espaço, e as tags são ordenadas alfabeticamente.
    string_agg(tags.name, ', ' ORDER BY tags.name) AS "tags"
FROM 
    topics t -- Os dados são selecionados da tabela 'topics'.
    -- A tabela 'topic_tags' é unida à tabela 'topics' usando 'topic_id'.
    LEFT JOIN topic_tags tt ON tt.topic_id = t.id
    -- A tabela 'tags' é unida à tabela 'topic_tags' usando 'tag_id'.
    LEFT JOIN tags ON tags.id = tt.tag_id
GROUP BY 
    t.id -- O resultado é agrupado pelo 'id' do tópico.
ORDER BY
    "tags" -- O resultado é ordenado por 'tags'.

Usuários que Postaram em Tópicos

Esta consulta retornará uma lista de ids e títulos de tópicos, os nomes de usuário dos usuários que postaram em cada tópico e a contagem de usuários distintos que postaram em cada tópico. Os resultados são então ordenados pela contagem de usuários, em ordem decrescente.

SELECT
    topics.id AS "topic_id",
    topics.title AS "topic_title",
    STRING_AGG(DISTINCT users.username, ', ' ORDER BY users.username) AS "users_posted",
    COUNT(DISTINCT users.id) AS "user_count"
FROM
    topics
JOIN
    posts ON posts.topic_id = topics.id
JOIN
    users ON users.id = posts.user_id
GROUP BY
    topics.id, topics.title
ORDER BY
    "user_count" DESC

Exemplo de Resultados

topic topic_title users_posted user_count
Lets make a topic (10) Lets make a topic anonymous, user1, user2, user3 4
Another Topic (3) Another Topic user3, user4, user5 3
Discobot test (2) Discobot test user6 1
Explicação Detalhada com Comentários Inline
-- Esta instrução SQL está selecionando dados das tabelas 'topics', 'posts' e 'users'.
SELECT
    topics.id AS "topic_id", -- Seleciona o 'id' da tabela 'topics'.
    topics.title AS "topic_title", -- Seleciona o 'title' da tabela 'topics'.
    -- A função STRING_AGG concatena os nomes de usuário dos usuários que postaram no tópico em uma única string.
    -- Cada nome de usuário é separado por uma vírgula e um espaço, e os nomes de usuário são ordenados alfabeticamente.
    STRING_AGG(DISTINCT users.username, ', ' ORDER BY users.username) AS "users_posted",
    -- Conta o número de usuários distintos que postaram no tópico.
    COUNT(DISTINCT users.id) AS "user_count"
FROM
    topics -- Os dados são selecionados da tabela 'topics'.
    -- A tabela 'posts' é unida à tabela 'topics' usando 'topic_id'.
    JOIN posts ON posts.topic_id = topics.id
    -- A tabela 'users' é unida à tabela 'posts' usando 'id'.
    JOIN users ON users.id = posts.user_id
GROUP BY
    topics.id, topics.title -- O resultado é agrupado pelo 'id' e 'title' do tópico.
ORDER BY
    "user_count" DESC -- O resultado é ordenado pelo número de usuários, em ordem decrescente.

É isso para este tutorial!

Se você tiver alguma dúvida ou exemplos de como usou string_agg, sinta-se à vontade para compartilhá-los abaixo. :slightly_smiling_face:

6 curtidas