(+351) 21 24 10006  ·  info@bconcepts.pt
Carnaxide, Lisboa

Cómo concatenar filas con STRING_AGG en SQL Server

João Barros 10 de July de 2026 4 min de lectura

Combinar valores de varias filas en una sola cadena separada por comas es una necesidad muy común en informes, listados y exportaciones de datos. Durante años, esto obligaba a trucos poco legibles con FOR XML PATH. Desde SQL Server 2017, la función STRING_AGG resuelve el mismo problema en una sola expresión, con código más simple, más rápido de escribir y fácil de mantener.

Requisitos previos

  • SQL Server 2017 o superior, o Azure SQL Database (la función STRING_AGG está disponible a partir de esa versión).
  • Una herramienta de consulta como SQL Server Management Studio (SSMS) o Azure Data Studio.
  • Conocimientos básicos de SELECT y GROUP BY.

Paso 1: Preparar una tabla de ejemplo

Para seguir el ejemplo, vamos a crear una pequeña tabla con ventas por vendedor. Cada fila representa un producto vendido por una persona, con un identificador numérico asociado. Ejecute el siguiente script en una base de datos de pruebas, nunca en producción:

CREATE TABLE Vendas (
    ProdutoId INT,
    Vendedor  NVARCHAR(50),
    Produto   NVARCHAR(50)
);

INSERT INTO Vendas (ProdutoId, Vendedor, Produto) VALUES
(101, 'Ana',   'Teclado'),
(102, 'Ana',   'Rato'),
(103, 'Ana',   'Webcam'),
(201, 'Bruno', 'Monitor'),
(202, 'Bruno', 'Cabo HDMI');

Observe que Ana tiene tres productos y Bruno tiene dos. Nuestro objetivo es obtener solo una fila por vendedor, con todos los productos reunidos en una única columna de texto.

Paso 2: Concatenar valores con STRING_AGG

La función STRING_AGG recibe dos argumentos: la expresión a concatenar y el separador que se coloca entre los valores. Cuando la combinamos con GROUP BY, cada grupo de filas se reduce a un único valor de texto:

SELECT
    Vendedor,
    STRING_AGG(Produto, ', ') AS Produtos
FROM Vendas
GROUP BY Vendedor;

El GROUP BY Vendedor define los grupos y STRING_AGG une todos los productos de cada vendedor, separados por una coma y un espacio. Con solo cuatro líneas de SQL obtenemos el resultado deseado, sin subconsultas ni funciones XML.

Paso 3: Ordenar los valores con WITHIN GROUP

Hay un detalle importante: de forma predeterminada, el orden de los valores concatenados no está garantizado por el motor. Si necesita un resultado predecible —por ejemplo, orden alfabético— añada la cláusula WITHIN GROUP con un ORDER BY:

SELECT
    Vendedor,
    STRING_AGG(Produto, ', ') WITHIN GROUP (ORDER BY Produto) AS Produtos
FROM Vendas
GROUP BY Vendedor;

Ahora los productos aparecen siempre en el mismo orden dentro de cada grupo. Esto es esencial cuando el resultado se compara entre ejecuciones o se usa en pruebas automatizadas.

Paso 4: Concatenar números e ignorar valores nulos

STRING_AGG solo opera sobre texto, por lo que las columnas numéricas o de fecha deben convertirse primero con CAST o CONVERT. Un detalle muy útil: la función ignora automáticamente los valores NULL, sin dejar separadores de más. Vea cómo concatenar los identificadores numéricos:

SELECT
    Vendedor,
    STRING_AGG(CAST(ProdutoId AS VARCHAR(10)), ';') AS Ids
FROM Vendas
GROUP BY Vendedor;

Si algún ProdutoId fuera NULL, simplemente se ignoraría, sin crear separadores duplicados ni requerir tratamiento manual.

Consejo: para generar una lista repartida en líneas en lugar de valores uno al lado del otro, use CHAR(10) como separador. Muchas herramientas muestran entonces cada elemento en su propia línea.

Verificar el resultado

Ejecute la consulta del Paso 3. Debe obtener exactamente dos filas, una por vendedor:

Vendedor  Produtos
--------  ---------------------------
Ana       Rato, Teclado, Webcam
Bruno     Cabo HDMI, Monitor

Si ve una fila por cada producto en lugar de una por vendedor, entonces falta el GROUP BY en la consulta. Si el orden de los productos no es el esperado, revise la cláusula WITHIN GROUP (ORDER BY ...).

Conclusión

Con una sola función, STRING_AGG sustituye soluciones complicadas y hace que la concatenación de filas sea legible y fácil de mantener. A partir de aquí, pruebe a combinarla con filtros WHERE para concatenar solo parte de los datos, usarla dentro de vistas para informes, o cambiar el separador por un salto de línea para crear listas verticales. ¿Cuál será la primera consulta de su proyecto donde sustituya un antiguo FOR XML PATH por STRING_AGG?