Usando STRING_AGG para resultados de consulta concisos

La función string_agg en SQL es una función de agregación que concatena (une) cadenas de múltiples filas en una sola cadena con varias opciones.

Es particularmente útil cuando deseas combinar valores de una columna para cada grupo de datos en tus informes, y puede hacer que el resultado de tu consulta sea más fácil de leer, especialmente cuando se trata de relaciones de muchos a muchos. Por ejemplo, si deseas crear un informe que muestre todas las etiquetas utilizadas en cada tema, podrías usar string_agg para concatenar todas las etiquetas de cada tema en una sola cadena.

Sintaxis

Aquí está la sintaxis básica de string_agg:

STRING_AGG(expresión, delimitador)

La función string_agg toma dos parámetros:

  • expresión: El valor que se concatenará.
  • delimitador: El delimitador que se insertará entre las cadenas. El delimitador puede ser una cadena o un carácter.

Ejemplo de Uso en Consultas DE

Veamos algunos ejemplos de consultas que utilizan string_agg

Listar Todas las Categorías en un Sitio

Esta consulta concatena los campos name e id de la tabla categories en una sola cadena, con cada par name e id separado por ’ : ', y cada par separado por ', '. Los pares se ordenan luego por id.

SELECT  
    -- La función STRING_AGG concatena los campos 'name' e 'id' en una sola cadena.
    -- Cada par 'name' e 'id' está separado por ' : ', y cada par está separado por ', '.
    -- Los pares se ordenan por 'id'.
    STRING_AGG(name || ' : ' || id, ', ' ORDER BY id) AS category_list
FROM 
    categories -- Los datos se seleccionan de la tabla 'categories'.

Resultados de Ejemplo:

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

Listar Todos los Temas y Etiquetas Asociadas

Esta consulta selecciona el id de la tabla topics y concatena las tags asociadas para cada tema en una sola cadena. Cada etiqueta está separada por una coma y un espacio, y las etiquetas se ordenan alfabéticamente. El resultado se agrupa por el id del tema y se ordena por las etiquetas. Si un tema no tiene etiquetas, la columna 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

El resultado será una lista de IDs de temas formateados, cada uno con una cadena de etiquetas asociadas ordenadas alfabéticamente. Por ejemplo:

Resultados de Ejemplo:

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
Explicación Detallada con Comentarios en Línea
-- Esta declaración SQL está seleccionando datos de la tabla 'topics' y 'tags' asociadas.
SELECT 
    t.id topic_id, -- Selecciona el 'id' de la tabla 'topics'.
    -- La función STRING_AGG concatena las 'tags' asociadas para cada tema en una sola cadena.
    -- Cada etiqueta está separada por una coma y un espacio, y las etiquetas se ordenan alfabéticamente.
    string_agg(tags.name, ', ' ORDER BY tags.name) AS "tags"
FROM 
    topics t -- Los datos se seleccionan de la tabla 'topics'.
    -- La tabla 'topic_tags' se une a la izquierda por 'topic_id' de la tabla 'topics'.
    LEFT JOIN topic_tags tt ON tt.topic_id = t.id
    -- La tabla 'tags' se une a la izquierda por 'tag_id' de la tabla 'topic_tags'.
    LEFT JOIN tags ON tags.id = tt.tag_id
GROUP BY 
    t.id -- El resultado se agrupa por el 'id' del tema.
ORDER BY
    "tags" -- El resultado se ordena por las 'tags'.

Usuarios que Han Publicado en Temas

Esta consulta devolverá una lista de ids y títulos de topic, los usernames de los usuarios que han publicado en cada tema, y el recuento de usuarios distintos que han publicado en cada tema. Los resultados se ordenan luego por el recuento de usuarios, en orden descendente.

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

Resultados de Ejemplo

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
Explicación Detallada con Comentarios en Línea
-- Esta declaración SQL está seleccionando datos de las tablas 'topics', 'posts' y 'users'.
SELECT
    topics.id AS "topic_id", -- Selecciona el 'id' de la tabla 'topics'.
    topics.title AS "topic_title", -- Selecciona el 'title' de la tabla 'topics'.
    -- La función STRING_AGG concatena los nombres de usuario de los usuarios que han publicado en el tema en una sola cadena.
    -- Cada nombre de usuario está separado por una coma y un espacio, y los nombres de usuario se ordenan alfabéticamente.
    STRING_AGG(DISTINCT users.username, ', ' ORDER BY users.username) AS "users_posted",
    -- Cuenta el número de usuarios distintos que han publicado en el tema.
    COUNT(DISTINCT users.id) AS "user_count"
FROM
    topics -- Los datos se seleccionan de la tabla 'topics'.
    -- La tabla 'posts' se une por 'topic_id' de la tabla 'topics'.
    JOIN posts ON posts.topic_id = topics.id
    -- La tabla 'users' se une por 'id' de la tabla 'posts'.
    JOIN users ON users.id = posts.user_id
GROUP BY
    topics.id, topics.title -- El resultado se agrupa por el 'id' y 'title' del tema.
ORDER BY
    "user_count" DESC -- El resultado se ordena por el número de usuarios, en orden descendente.

¡Eso es todo para este tutorial!

Si tienes alguna pregunta o ejemplos de cómo has usado string_agg, no dudes en compartirlos a continuación. :slightly_smiling_face:

6 Me gusta