STRING_AGG (Transact-SQL)

Se aplica a: SQL Server 2017 (14.x) y versiones posteriores, Azure SQL Database Azure SQL Instancia administrada punto de conexión de SQL Analytics de Azure Synapse Analytics en Microsoft Fabric Warehouse en Microsoft Fabric

Concatena los valores de expresiones de cadena y coloca valores de separador entre ellos. El separador no se agrega al final de la cadena.

Convenciones de sintaxis de Transact-SQL

Sintaxis

STRING_AGG ( expression, separator ) [ <order_clause> ]

<order_clause> ::=   
    WITHIN GROUP ( ORDER BY <order_by_expression_list> [ ASC | DESC ] )   

Argumentos

expression
Es una expresión de cualquier tipo. Las expresiones se convierten en tipos NVARCHAR o VARCHAR durante la concatenación. Los tipos que no son de cadena se convierten en NVARCHAR.

separator
Es una expresión de tipo NVARCHAR o VARCHAR que se usa como separador de cadenas concatenadas. Puede ser un literal o una variable.

<order_clause>
Si quiere, especifique el orden de los resultados concatenados con la cláusula WITHIN GROUP:

WITHIN GROUP ( ORDER BY <order_by_expression_list> [ ASC | DESC ] )

<order_by_expression_list>

Lista de expresiones no constantes que se pueden usar para ordenar los resultados. Solo se permite un parámetro order_by_expression por consulta. El criterio de ordenación predeterminado es ascendente.

Tipos de valor devuelto

El tipo de valor devuelto depende del primer argumento (expresión). Si el argumento de entrada es de tipo string (NVARCHAR, VARCHAR), el tipo del resultado será igual que el tipo de la entrada. En la siguiente tabla se enumeran las conversiones automáticas:

Tipo de expresión de entrada Resultado
NVARCHAR(MAX) NVARCHAR(MAX)
VARCHAR(MAX) VARCHAR(MAX)
NVARCHAR(1...4000) NVARCHAR(4000)
VARCHAR(1...8000) VARCHAR(8000)
int, bigint, smallint, tinyint, numeric, float, real, bit, decimal, smallmoney, money, datetime, datetime2 NVARCHAR(4000)

Comentarios

STRING_AGG es una función de agregado que toma todas las expresiones de las filas y las concatena en una sola cadena. Los valores de la expresión se convierten implícitamente a tipos string y, después, se concatenan. La conversión implícita de cadenas sigue las reglas existentes para las conversiones de tipos de datos. Para más información sobre las conversiones de tipo de datos, vea CAST y CONVERT (Transact-SQL).

Si la expresión de entrada es de tipo VARCHAR, el separador no puede ser de tipo NVARCHAR.

Los valores NULL se omiten y no se agrega el separador correspondiente. Para devolver un marcador de posición para valores NULL, use la función ISNULL como se muestra en el ejemplo B.

STRING_AGG está disponible en cualquier nivel de compatibilidad.

Nota

<order_clause> está disponible con el nivel de compatibilidad de base de datos 110 y versiones posteriores.

Ejemplos

La mayoría de los ejemplos de este artículo hacen referencia a las bases de datos de ejemplo AdventureWorks.

A. Generar una lista de nombres separados en líneas nuevas

En el siguiente ejemplo se genera una lista de nombres en una única celda de resultados separados por retornos de carro.

USE AdventureWorks2022;
GO
SELECT STRING_AGG (CONVERT(NVARCHAR(max),FirstName), CHAR(13)) AS csv 
FROM Person.Person;
GO

Este es el conjunto de resultados.

csv
Syed
Catherine
Kim
Kim
Kim
Hazem
...

Los valores NULL detectados en las celdas name no se incluyen en el resultado.

Nota

Si usa el Editor de consultas de SQL Server Management Studio, la opción Resultados a cuadrícula no puede implementar el retorno de carro. Cambie a Resultados a texto para ver el resultado configurado correctamente.
De forma predeterminada, los resultados a texto se truncan a 256 caracteres. Para aumentar este límite, cambie la opción Número máximo de caracteres mostrados en cada columna.

B. Generar una lista de nombres separados por coma sin valores NULL

En el siguiente ejemplo los valores NULL se reemplazan por "N/A" y se devuelven los nombres separados por comas en una única celda de resultados.

USE AdventureWorks2022;
GO
SELECT STRING_AGG(CONVERT(NVARCHAR(max), ISNULL(FirstName,'N/A')), ',') AS csv 
FROM Person.Person;
GO

Este es el conjunto de resultados.

Nota:

Los resultados se muestran recortados.

csv
Syed,Catherine,Kim,Kim,Kim,Hazem,Sam,Humberto,Gustavo,Pilar,Pilar, ...

C. Generar nombres separados por comas

USE AdventureWorks2022;
GO
SELECT STRING_AGG(CONVERT(NVARCHAR(max), CONCAT(FirstName, ' ', LastName, '(', ModifiedDate, ')')), CHAR(13)) AS names 
FROM Person.Person;
GO

Este es el conjunto de resultados.

Nota:

Los resultados se muestran recortados.

Nombres
Ken Sánchez (8 de febrero de 2003, 00:00)
Terri Duffy (24 de febrero de 2002, 00:00)
Roberto Tamburello (5 de diciembre de 2001, 00:00)
Rob Walters (29 de diciembre de 2001, 00:00)
...

Nota

Si usa el Editor de consultas de Management Studio, la opción Resultados a cuadrícula no puede implementar el retorno de carro. Cambie a Resultados a texto para ver el resultado configurado correctamente.

Imagine una base de datos donde los artículos y sus etiquetas se separan en tablas diferentes. Un desarrollador quiere que se devuelva una fila por cada artículo con todas las etiquetas asociadas. La consulta siguiente logra este resultado:

SELECT a.articleId, title, STRING_AGG (tag, ',') as tags
FROM dbo.Article AS a
LEFT JOIN dbo.ArticleTag AS t
    ON a.ArticleId = t.ArticleId
GROUP BY a.articleId, title;
GO

Este es el conjunto de resultados.

articleId title etiquetas
172 Los sondeos vaticinan unos resultados electorales ajustados política,sondeos,ayuntamiento
176 Se espera que la nueva autopista reduzca la congestión NULL
177 Los perros siguen siendo más populares que los gatos sondeos,animales

Nota

La cláusula GROUP BY es necesaria si la función STRING_AGG no es el único elemento de la lista SELECT.

E. Generar una lista de correos electrónicos por ciudades

Con la siguiente consulta se buscan las direcciones de correo electrónico de los empleados y se agrupan por ciudad:

USE AdventureWorks2022;
GO

SELECT TOP 10 City, STRING_AGG(CONVERT(NVARCHAR(max), EmailAddress), ';') AS emails 
FROM Person.BusinessEntityAddress AS BEA  
INNER JOIN Person.Address AS A ON BEA.AddressID = A.AddressID
INNER JOIN Person.EmailAddress AS EA ON BEA.BusinessEntityID = EA.BusinessEntityID 
GROUP BY City;
GO

Este es el conjunto de resultados.

Nota:

Los resultados se muestran recortados.

City emails
Ballard paige28@adventure-works.com;joshua24@adventure-works.com;;javier12@adventure-works.com ...
Baltimore gilbert9@adventure-works.com
Barstow kristen4@adventure-works.com
Basingstoke Hants dale10@adventure-works.com;heidi9@adventure-works.com
Baytown kelvin15@adventure-works.com
Beaverton billy6@adventure-works.com;dalton35@adventure-works.com;;lawrence1@adventure-works.com ...
Bell Gardens christy8@adventure-works.com
Bellevue min0@adventure-works.com;gigi0@adventure-works.com;;terry18@adventure-works.com ...
Bellflower philip0@adventure-works.com;emma34@adventure-works.com;;jorge8@adventure-works.com ...
Bellingham christopher23@adventure-works.com;frederick7@adventure-works.com;;omar0@adventure-works.com ...

Los correos electrónicos devueltos en la columna emails se pueden usar para enviar mensajes de correo electrónico al grupo de personas que trabajan en determinadas ciudades.

F. Generar una lista ordenada de correos electrónicos por ciudades

Al igual que el ejemplo anterior, con la siguiente consulta se buscan las direcciones de correo electrónico de los empleados, se agrupan por ciudad y se ordenan alfabéticamente:

USE AdventureWorks2022;
GO

SELECT TOP 10 City, STRING_AGG(CONVERT(NVARCHAR(max), EmailAddress), ';') WITHIN GROUP (ORDER BY EmailAddress ASC) AS Emails 
FROM Person.BusinessEntityAddress AS BEA  
INNER JOIN Person.Address AS A ON BEA.AddressID = A.AddressID
INNER JOIN Person.EmailAddress AS EA ON BEA.BusinessEntityID = EA.BusinessEntityID 
GROUP BY City;
GO

Este es el conjunto de resultados.

Nota:

Los resultados se muestran recortados.

City Correos electrónicos
Barstow kristen4@adventure-works.com
Basingstoke Hants dale10@adventure-works.com;heidi9@adventure-works.com
Braintree mindy20@adventure-works.com
Bell Gardens christy8@adventure-works.com
Byron louis37@adventure-works.com
Bordeaux ranjit0@adventure-works.com
Carnation don0@adventure-works.com;douglas0@adventure-works.com;;george0@adventure-works.com ...
Boulogne-Billancourt allen12@adventure-works.com;bethany15@adventure-works.com;;carl5@adventure-works.com ...
Berkshire barbara41@adventure-works.com;brenda4@adventure-works.com;;carrie14@adventure-works.com ...
Berks adriana6@adventure-works.com;alisha13@adventure-works.com;;arthur19@adventure-works.com ...

Pasos siguientes

Aprenda más sobre las funciones de Transact-SQL en los artículos siguientes: