¿Cómo concatenar texto de varias filas en una sola cadena de texto en el servidor SQL?

Considere una tabla de base de datos con nombres, con tres filas:

Peter
Paul
Mary

¿Existe una manera fácil de convertir esto en una sola cadena de Peter, Paul, Mary?

preguntado Oct 11 '08, 21:10

Para obtener respuestas específicas de SQL Server, intente esta pregunta. -

Para MySQL, consulte Grupo_Concat del esta respuesta -

Desearía que la próxima versión de SQL Server ofreciera una nueva característica para resolver la concatenación de cadenas de varias filas de manera elegante sin las tonterías de FOR XML PATH. -

No es SQL, pero si se trata de algo que se realiza una sola vez, puede pegar la lista en esta herramienta del navegador. convert.town/column-to-comma-separated-list -

En Oracle, puede usar LISTAGG (COLUMN_NAME) de 11g r2 antes de que exista una función no compatible llamada WM_CONCAT (COLUMN_NAME) que hace lo mismo. -

30 Respuestas

Si está en SQL Server 2017 o Azure, consulte Respuesta de Mathieu Renda.

Tuve un problema similar cuando intentaba unir dos tablas con relaciones de uno a varios. En SQL 2005 encontré que XML PATH El método puede manejar la concatenación de filas muy fácilmente.

Si hay una mesa llamada STUDENTS

SubjectID       StudentName
----------      -------------
1               Mary
1               John
1               Sam
2               Alaina
2               Edward

El resultado que esperaba fue:

SubjectID       StudentName
----------      -------------
1               Mary, John, Sam
2               Alaina, Edward

Utilicé lo siguiente T-SQL:

SELECT Main.SubjectID,
       LEFT(Main.Students,Len(Main.Students)-1) As "Students"
FROM
    (
        SELECT DISTINCT ST2.SubjectID, 
            (
                SELECT ST1.StudentName + ',' AS [text()]
                FROM dbo.Students ST1
                WHERE ST1.SubjectID = ST2.SubjectID
                ORDER BY ST1.SubjectID
                FOR XML PATH ('')
            ) [Students]
        FROM dbo.Students ST2
    ) [Main]

Puede hacer lo mismo de una manera más compacta si puede colocar las comas al principio y usar substring para omitir el primero para que no necesite hacer una subconsulta:

SELECT DISTINCT ST2.SubjectID, 
    SUBSTRING(
        (
            SELECT ','+ST1.StudentName  AS [text()]
            FROM dbo.Students ST1
            WHERE ST1.SubjectID = ST2.SubjectID
            ORDER BY ST1.SubjectID
            FOR XML PATH ('')
        ), 2, 1000) [Students]
FROM dbo.Students ST2

Respondido 02 ago 18, 12:08

Gran solucion Lo siguiente puede ser útil si necesita manejar caracteres especiales como los de HTML: Rob Farley: Manejo de caracteres especiales con FOR XML PATH (''). - usuario140628

Aparentemente, esto no funciona si los nombres contienen caracteres XML como < or &. Vea el comentario de @ BenHinman. - Diana

NB: Este método depende del comportamiento indocumentado de FOR XML PATH (''). Eso significa que no debe considerarse confiable ya que cualquier parche o actualización podría alterar su funcionamiento. Básicamente se basa en una función obsoleta. - Pedacitos de tocino

@Whelkaholism La conclusión es que FOR XML está destinado a generar XML, no a concatenar cadenas arbitrarias. Por eso se escapa &, < y > a códigos de entidad XML (&amp;, &lt;, &gt;). Supongo que también se escapará " y ' a &quot; y &apos; en atributos también. Es no GROUP_CONCAT(), string_agg(), array_agg(), listagg(), etc., incluso si puedes hacer que lo haga. Nosotros tienes dedicar nuestro tiempo a exigir que Microsoft implemente una función adecuada. - Pedacitos de tocino

Buenas noticias: MS SQL Server agregará string_agg en v.Next. y todo esto puede desaparecer. - Jason C

Esta respuesta puede volver resultados inesperados Para obtener resultados consistentes, use uno de los métodos FOR XML PATH detallados en otras respuestas.

Utilice la herramienta COALESCE:

DECLARE @Names VARCHAR(8000) 
SELECT @Names = COALESCE(@Names + ', ', '') + Name 
FROM People

Solo una explicación (ya que esta respuesta parece obtener vistas relativamente regulares):

  • Coalesce es realmente un truco útil que logra dos cosas:

1) No es necesario inicializar @Names con un valor de cadena vacío.

2) No es necesario quitar un separador adicional al final.

  • La solución anterior dará resultados incorrectos si una fila tiene una NULL Valor de nombre (si hay un NULL, la NULL hará @Names NULL después de esa fila, y la siguiente fila comenzará de nuevo como una cadena vacía. Se arregla fácilmente con una de dos soluciones:
DECLARE @Names VARCHAR(8000) 
SELECT @Names = COALESCE(@Names + ', ', '') + Name
FROM People
WHERE Name IS NOT NULL

o bien:

DECLARE @Names VARCHAR(8000) 
SELECT @Names = COALESCE(@Names + ', ', '') + 
    ISNULL(Name, 'N/A')
FROM People

Dependiendo del comportamiento que desee (la primera opción solo filtra NULLs fuera, la segunda opción los mantiene en la lista con un mensaje de marcador [reemplace 'N / A' con lo que sea apropiado para usted]).

Respondido 30 Abr '19, 13:04

Para ser claros, coalesce no tiene nada que ver con la creación de la lista, solo se asegura de que los valores NULL no estén incluidos. - Graeme Perrow

@Graeme Perrow No excluye los valores NULL (se requiere un DONDE para eso, esto perder resultados si uno de los valores de entrada es NULL), y se requiere en este enfoque porque: NULL + no NULL -> NULL y no NULL + NULL -> NULL; también @Name es NULL por defecto y, de hecho, esa propiedad se usa aquí como un centinela implícito para determinar si se debe agregar un ',' o no. - usuario166390

Tenga en cuenta que este método de concatenación se basa en SQL Server que ejecuta la consulta con un plan en particular. Me han sorprendido usando este método (con la adición de un ORDER BY). Cuando se trataba de una pequeña cantidad de filas, funcionó bien, pero con más datos, SQL Server eligió un plan diferente que resultó en la selección del primer elemento sin concatenación alguna. Ver este artículo por Anith Sen. - fbarbero

Este método no se puede usar como una subconsulta en una lista de selección o cláusula where, porque usa una variable tSQL. En tales casos, puede utilizar los métodos ofrecidos por @Ritesh: R. Schreurs

Este no es un método confiable de concatenación. No es compatible y no debe usarse (según Microsoft, p. Ej. support.microsoft.com/en-us/kb/287515, connect.microsoft.com/SQLServer/Feedback/Details/704389). Puede cambiar sin previo aviso. Utilice la técnica XML PATH discutida en stackoverflow.com/questions/5031204/… Escribí más aquí: marc.durdin.net/2015/07/… - marc durdin

SQL Server 2017+ y SQL Azure: STRING_AGG

Comenzando con la próxima versión de SQL Server, finalmente podemos concatenar entre filas sin tener que recurrir a ninguna variable o brujería XML.

STRING_AGG (Transact-SQL)

Sin agrupar

SELECT STRING_AGG(Name, ', ') AS Departments
FROM HumanResources.Department;

Con agrupación:

SELECT GroupName, STRING_AGG(Name, ', ') AS Departments
FROM HumanResources.Department
GROUP BY GroupName;

Con agrupación y subclasificación

SELECT GroupName, STRING_AGG(Name, ', ') WITHIN GROUP (ORDER BY Name ASC) AS Departments
FROM HumanResources.Department 
GROUP BY GroupName;

Respondido el 20 de junio de 20 a las 10:06

Y, a diferencia de las soluciones CLR, usted tiene control sobre la clasificación. - canon

Parece haber una limitación de visualización de 4000 caracteres en STRING_AGG - Inspirado por

¿Hay alguna forma de ordenar en caso de que no haya GRUPO POR (por ejemplo, para el ejemplo "Sin agrupamiento")? - RuudvK

Actualización: logré hacer lo siguiente, pero ¿hay una manera más limpia? SELECCIONE STRING_AGG (Nombre, ',') COMO Departamentos DE (SELECCIONE EL TOP 100000 Nombre DE HumanResources.Department ORDENE POR Nombre) D; - RuudvK

Tuve que lanzarlo a NVarchar (max) para que funcionara .. `` `SELECT STRING_AGG (CAST (EmpName as NVARCHAR (MAX)), ',') FROM EmpTable as t '' - Varun

Un método aún no se muestra a través del XML data() comando en MS SQL Server es:

Suponga una tabla llamada NameList con una columna llamada FName,

SELECT FName + ', ' AS 'data()' 
FROM NameList 
FOR XML PATH('')

devoluciones:

"Peter, Paul, Mary, "

Solo se debe tratar la coma adicional.

Edit: Como se adoptó del comentario de @ NReilingh, puede usar el siguiente método para eliminar la coma al final. Suponiendo los mismos nombres de tabla y columna:

STUFF(REPLACE((SELECT '#!' + LTRIM(RTRIM(FName)) AS 'data()' FROM NameList
FOR XML PATH('')),' #!',', '), 1, 2, '') as Brands

Respondido 25 Abr '16, 16:04

santa mierda eso es increíble! Cuando se ejecuta por sí solo, como en su ejemplo, el resultado se formatea como un hipervínculo, que cuando se hace clic (en SSMS) abre una nueva ventana que contiene los datos, pero cuando se usa como parte de una consulta más grande, simplemente aparece como una cadena. ¿Es una cuerda? ¿O es xml que necesito tratar de manera diferente en la aplicación que usará estos datos? - paquet

Este enfoque también escapa caracteres XML como <y>. Entonces, SELECCIONAR ' ' + FName + ' ' da como resultado "<b> John </b> <b> Paul ..." - Lukáš Lánský

Solución ordenada. Me doy cuenta de que incluso cuando no agrego el + ', ' todavía agrega un espacio único entre cada elemento concatenado. - baodad

@Baodad Eso parece ser parte del trato. Puede solucionarlo reemplazando un carácter de token agregado. Por ejemplo, esto hace una lista perfecta delimitada por comas para cualquier longitud: SELECT STUFF(REPLACE((SELECT '#!'+city AS 'data()' FROM #cityzip FOR XML PATH ('')),' #!',', '),1,2,'') - NReilingh

Vaya, en realidad, en mis pruebas, el uso de datos () y un reemplazo es MUCHO más eficaz que no. Súper raro. - NReilingh

In SQL Server 2005

SELECT Stuff(
  (SELECT N', ' + Name FROM Names FOR XML PATH(''),TYPE)
  .value('text()[1]','nvarchar(max)'),1,2,N'')

En SQL Server 2016

se puede utilizar el PARA la sintaxis JSON

es decir,

SELECT per.ID,
Emails = JSON_VALUE(
   REPLACE(
     (SELECT _ = em.Email FROM Email em WHERE em.Person = per.ID FOR JSON PATH)
    ,'"},{"_":"',', '),'$[0]._'
) 
FROM Person per

Y el resultado se convertirá

Id  Emails
1   abc@gmail.com
2   NULL
3   def@gmail.com, xyz@gmail.com

Esto funcionará incluso si sus datos contienen caracteres XML no válidos.

'"},{"_":"' es seguro porque si tus datos contienen '"},{"_":"', se escapará a "},{\"_\":\"

Puedes reemplazar ', ' con cualquier separador de cadenas


Y en SQL Server 2017, Azure SQL Database

Puedes usar el nuevo Función STRING_AGG

Respondido 23 Jul 18, 17:07

Buen uso de la función STUFF para rechazar los dos caracteres principales. - David

Me gusta más esta solución, porque puedo usarla fácilmente en una lista de selección agregando 'como '. No estoy seguro de cómo hacer esto con la solución de @Ritesh. - R. Schreurs

Esto es mejor que la respuesta aceptada porque esta opción también maneja caracteres reservados XML sin escape, como <, >, &, etc.que FOR XML PATH('') escapará automáticamente. - batetech

En MySQL, hay una función, GROUP_CONCAT (), que le permite concatenar los valores de varias filas. Ejemplo:

SELECT 1 AS a, GROUP_CONCAT(name ORDER BY name ASC SEPARATOR ', ') AS people 
FROM users 
WHERE id IN (1,2,3) 
GROUP BY a

Respondido 27 Oct 20, 00:10

Funciona básicamente. Dos cosas a considerar: 1) si su columna no es una CHAR, debes emitirlo, por ejemplo, a través de GROUP_CONCAT( CAST(id AS CHAR(8)) ORDER BY id ASC SEPARATOR ',') 2) si tiene muchos valores, debe aumentar el group_concat_max_len como está escrito en stackoverflow.com/a/1278210/1498405 - duro

Utilice la herramienta JUNTARSE - Obtenga más información aquí.

Para un ejemplo:

102

103

104

Luego escriba el código a continuación en el servidor SQL,

Declare @Numbers AS Nvarchar(MAX) -- It must not be MAX if you have few numbers 
SELECT  @Numbers = COALESCE(@Numbers + ',', '') + Number
FROM   TableName where Number IS NOT NULL

SELECT @Numbers

La salida sería:

102,103,104

Respondido el 23 de Septiembre de 17 a las 00:09

Esta es realmente la mejor solución en mi opinión, ya que evita los problemas de codificación que presenta FOR XML. solía Declare @Numbers AS Nvarchar(MAX) y funcionó bien. ¿Puede explicar por qué recomienda no usarlo, por favor? - Malvado

¡Esta solución ya se publicó hace 8 años! stackoverflow.com/a/194887/986862 - André Figueiredo

¿Por qué devuelve esta consulta ??? símbolos en lugar de cirílicos? ¿Es esto solo un problema de salida? - Akmal Salikhov

Las matrices de Postgres son increíbles. Ejemplo:

Cree algunos datos de prueba:

postgres=# \c test
You are now connected to database "test" as user "hgimenez".
test=# create table names (name text);
CREATE TABLE                                      
test=# insert into names (name) values ('Peter'), ('Paul'), ('Mary');                                                          
INSERT 0 3
test=# select * from names;
 name  
-------
 Peter
 Paul
 Mary
(3 rows)

Agréguelos en una matriz:

test=# select array_agg(name) from names;
 array_agg     
------------------- 
 {Peter,Paul,Mary}
(1 row)

Convierta la matriz en una cadena delimitada por comas:

test=# select array_to_string(array_agg(name), ', ') from names;
 array_to_string
-------------------
 Peter, Paul, Mary
(1 row)

LISTO

Desde PostgreSQL 9.0 es aún más fácil.

contestado el 23 de mayo de 17 a las 13:05

Si necesita más de una columna, por ejemplo, su identificación de empleado entre paréntesis, use el operador concat: select array_to_string(array_agg(name||'('||id||')' - Richard Fox

No aplicable a servidor SQL, solo para mysql - Obispo de oro

Oracle 11g Release 2 admite la función LISTAGG. Documentación aquí.

COLUMN employees FORMAT A50

SELECT deptno, LISTAGG(ename, ',') WITHIN GROUP (ORDER BY ename) AS employees
FROM   emp
GROUP BY deptno;

    DEPTNO EMPLOYEES
---------- --------------------------------------------------
        10 CLARK,KING,MILLER
        20 ADAMS,FORD,JONES,SCOTT,SMITH
        30 ALLEN,BLAKE,JAMES,MARTIN,TURNER,WARD

3 rows selected.

advertencia

Tenga cuidado al implementar esta función si existe la posibilidad de que la cadena resultante supere los 4000 caracteres. Lanzará una excepción. Si ese es el caso, entonces debe manejar la excepción o ejecutar su propia función que evita que la cadena unida supere los 4000 caracteres.

respondido 14 mar '13, 14:03

Para versiones anteriores de Oracle, wm_concat es perfecto. Su uso se explica en el enlace regalo de Alex. ¡Gracias Alex! - toscanelli

LISTAGG funciona perfecto! Simplemente lea el documento vinculado aquí. wm_concat eliminado de la versión 12c en adelante. - pregunta

En SQL Server 2005 y versiones posteriores, utilice la consulta siguiente para concatenar las filas.

DECLARE @t table
(
    Id int,
    Name varchar(10)
)
INSERT INTO @t
SELECT 1,'a' UNION ALL
SELECT 1,'b' UNION ALL
SELECT 2,'c' UNION ALL
SELECT 2,'d' 

SELECT ID,
stuff(
(
    SELECT ','+ [Name] FROM @t WHERE Id = t.Id FOR XML PATH('')
),1,1,'') 
FROM (SELECT DISTINCT ID FROM @t ) t

Respondido 20 Oct 14, 09:10

Creo que esto falla cuando los valores contienen símbolos XML como < or &. - Diana

No tengo acceso a un servidor SQL en casa, así que supongo que la sintaxis aquí, pero es más o menos:

DECLARE @names VARCHAR(500)

SELECT @names = @names + ' ' + Name
FROM Names

Respondido 12 Oct 08, 01:10

Debería iniciar @names en algo que no sea nulo, de lo contrario obtendrá NULL en todo momento; también necesitaría manejar el delimitador (incluido el innecesario) - Marc Gravell ♦

el único problema con este enfoque (que uso todo el tiempo) es que no se puede incrustar - ekkis

Para deshacerse del espacio inicial, cambie la consulta a SELECT @names = @names + CASE WHEN LEN(@names)=0 THEN '' ELSE ' ' END + Name FROM Names - Tian van Heerden

Además, debes comprobar que Name no sea nulo, puedes hacerlo haciendo: SELECT @names = @names + ISNULL(' ' + Name, '') - Vita1ij

Se sugirió una solución CTE recursiva, pero no se proporcionó ningún código. El siguiente código es un ejemplo de CTE recursivo. Tenga en cuenta que aunque los resultados coinciden con la pregunta, los datos no exactamente coincida con la descripción dada, ya que supongo que realmente desea hacer esto en grupos de filas, no en todas las filas de la tabla. Cambiarlo para que coincida con todas las filas de la tabla se deja como ejercicio para el lector.

;WITH basetable AS (
    SELECT
        id,
        CAST(name AS VARCHAR(MAX)) name, 
        ROW_NUMBER() OVER (Partition BY id ORDER BY seq) rw, 
        COUNT(*) OVER (Partition BY id) recs 
    FROM (VALUES
        (1, 'Johnny', 1),
        (1, 'M', 2), 
        (2, 'Bill', 1),
        (2, 'S.', 4),
        (2, 'Preston', 5),
        (2, 'Esq.', 6),
        (3, 'Ted', 1),
        (3, 'Theodore', 2),
        (3, 'Logan', 3),
        (4, 'Peter', 1),
        (4, 'Paul', 2),
        (4, 'Mary', 3)
    ) g (id, name, seq)
),
rCTE AS (
    SELECT recs, id, name, rw
    FROM basetable
    WHERE rw = 1

    UNION ALL

    SELECT b.recs, r.ID, r.name +', '+ b.name name, r.rw + 1
    FROM basetable b
    INNER JOIN rCTE r ON b.id = r.id AND b.rw = r.rw + 1
)
SELECT name
FROM rCTE
WHERE recs = rw AND ID=4

Respondido 26 ago 19, 19:08

Para los atónitos: esta consulta inserta 12 filas (3 columnas) en una tabla base temporal, luego crea una Expresión de tabla común recursiva (rCTE) y luego aplana el name columna en una cadena separada por comas para 4 grupos of ids. A primera vista, creo que esto es más trabajo que lo que hacen la mayoría de las otras soluciones para SQL Server. - knb

@knb: no estoy seguro si eso es un elogio, una condena o simplemente una sorpresa. La tabla base es porque me gusta que mis ejemplos realmente funcionen, realmente no tiene nada que ver con la pregunta. - jmoreno

Necesita crear una variable que contenga su resultado final y seleccione en él, así.

Solución más sencilla

DECLARE @char VARCHAR(MAX);

SELECT @char = COALESCE(@char + ', ' + [column], [column]) 
FROM [table];

PRINT @char;

respondido 15 nov., 16:21

En SQL Server vNext, esto se integrará con la función STRING_AGG, lea más sobre esto aquí: https://msdn.microsoft.com/en-us/library/mt790580.aspx

Respondido el 10 de enero de 17 a las 15:01

El uso de XML me ayudó a separar las filas con comas. Para la coma adicional, podemos usar la función de reemplazo de SQL Server. En lugar de agregar una coma, el uso de AS 'data ()' concatenará las filas con espacios, que luego se pueden reemplazar con comas como la sintaxis escrita a continuación.

REPLACE(
        (select FName AS 'data()'  from NameList  for xml path(''))
         , ' ', ', ') 

Respondido 26 Feb 12, 18:02

Esta es la mejor respuesta aquí en mi opinión. El uso de declare variable no es bueno cuando necesita unirse a otra tabla, y esto es agradable y breve. Buen trabajo. - david rossel

eso no funciona bien si los datos de FName ya tienen espacios, por ejemplo, "Mi nombre" - papelera

Realmente me está funcionando en ms-sql 2016 Seleccione REPLACE ((seleccione Name AS 'data ()' from Brand Where Id IN (1,2,3,4) for xml path ('')), '', ' , ') como allBrands - Rejwanul Reja

Una solución lista para usar, sin comas adicionales:

select substring(
        (select ', '+Name AS 'data()' from Names for xml path(''))
       ,3, 255) as "MyList"

Una lista vacía dará como resultado un valor NULO. Por lo general, insertará la lista en una columna de tabla o variable de programa: ajuste la longitud máxima de 255 a sus necesidades.

(Diwakar y Jens Frandsen proporcionaron buenas respuestas, pero necesitan mejorar).

Respondido 26 Feb 12, 20:02

Hay un espacio antes de la coma cuando se usa esto :( - Slayernoah

Solo reemplaza ', ' ',' si no quieres el espacio extra. - daniel reyes

SELECT STUFF((SELECT ', ' + name FROM [table] FOR XML PATH('')), 1, 2, '')

Aquí hay una muestra:

DECLARE @t TABLE (name VARCHAR(10))
INSERT INTO @t VALUES ('Peter'), ('Paul'), ('Mary')
SELECT STUFF((SELECT ', ' + name FROM @t FOR XML PATH('')), 1, 2, '')
--Peter, Paul, Mary

Respondido 28 Feb 18, 16:02

Con las otras respuestas, la persona que lee la respuesta debe conocer una tabla de dominio específico, como vehículo o estudiante. La tabla debe crearse y completarse con datos para probar una solución.

A continuación se muestra un ejemplo que utiliza la tabla "Information_Schema.Columns" de SQL Server. Al usar esta solución, no es necesario crear tablas ni agregar datos. Este ejemplo crea una lista de nombres de columna separados por comas para todas las tablas de la base de datos.

SELECT
    Table_Name
    ,STUFF((
        SELECT ',' + Column_Name
        FROM INFORMATION_SCHEMA.Columns Columns
        WHERE Tables.Table_Name = Columns.Table_Name
        ORDER BY Column_Name
        FOR XML PATH ('')), 1, 1, ''
    )Columns
FROM INFORMATION_SCHEMA.Columns Tables
GROUP BY TABLE_NAME 

contestado el 04 de mayo de 16 a las 20:05

DECLARE @Names VARCHAR(8000)
SELECT @name = ''
SELECT @Names = @Names + ',' + Names FROM People
SELECT SUBSTRING(2, @Names, 7998)

Esto pone la coma perdida al principio.

Sin embargo, si necesita otras columnas o CSV en una tabla secundaria, debe envolverla en un campo escalar definido por el usuario (UDF).

También puede usar la ruta XML como una subconsulta correlacionada en la cláusula SELECT (pero tendría que esperar hasta volver al trabajo porque Google no hace las cosas del trabajo en casa :-)

Respondido 26 Feb 12, 18:02

Esto funcionó para míServidor Sql 2016):

SELECT CarNamesString = STUFF((
         SELECT ',' + [Name]
            FROM tbl_cars 
            FOR XML PATH('')
         ), 1, 1, '')

Aquí está la fuente: https://www.mytecbits.com/

Y una solucion para MySql (ya que esta página aparece en Google para MySql)

SELECT [Name],
       GROUP_CONCAT(DISTINCT [Name]  SEPARATOR ',')
       FROM tbl_cars

Desde Documentaciones MySql

Respondido el 15 de enero de 20 a las 09:01

Para bases de datos de Oracle, consulte esta pregunta: ¿Cómo se pueden concatenar varias filas en una en Oracle sin crear un procedimiento almacenado?

La mejor respuesta parece ser @Emmanuel, usando la función incorporada LISTAGG (), disponible en Oracle 11g Release 2 y posteriores.

SELECT question_id,
   LISTAGG(element_id, ',') WITHIN GROUP (ORDER BY element_id)
FROM YOUR_TABLE;
GROUP BY question_id

como señaló @ user762952, y de acuerdo con la documentación de Oracle http://www.oracle-base.com/articles/misc/string-aggregation-techniques.php, la función WM_CONCAT () también es una opción. Parece estable, pero Oracle recomienda explícitamente no usarlo para ninguna aplicación SQL, así que úselo bajo su propio riesgo.

Aparte de eso, tendrá que escribir su propia función; el documento de Oracle anterior tiene una guía sobre cómo hacerlo.

contestado el 23 de mayo de 17 a las 12:05

Para evitar valores nulos, puede usar CONCAT ()

DECLARE @names VARCHAR(500)
SELECT @names = CONCAT(@names, ' ', name) 
FROM Names
select @names

Respondido 12 Feb 15, 12:02

Sería bueno saber porque CONCAT funciona. Un enlace a MSDN estaría bien. - Ingeniero invertido

Ejemplo completo de MySQL:

Tenemos usuarios que pueden tener muchos datos y queremos tener una salida, donde podemos ver todos los datos de los usuarios en una lista:

Resultado:

___________________________
| id   |  rowList         |
|-------------------------|
| 0    | 6, 9             |
| 1    | 1,2,3,4,5,7,8,1  |
|_________________________|

Configuración de la mesa:

CREATE TABLE `Data` (
  `id` int(11) NOT NULL,
  `user_id` int(11) NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=latin1;


INSERT INTO `Data` (`id`, `user_id`) VALUES
(1, 1),
(2, 1),
(3, 1),
(4, 1),
(5, 1),
(6, 0),
(7, 1),
(8, 1),
(9, 0),
(10, 1);


CREATE TABLE `User` (
  `id` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;


INSERT INTO `User` (`id`) VALUES
(0),
(1);

consulta:

SELECT User.id, GROUP_CONCAT(Data.id ORDER BY Data.id) AS rowList FROM User LEFT JOIN Data ON User.id = Data.user_id GROUP BY User.id

Respondido 22 Jul 15, 08:07

Realmente me gustó la elegancia de La respuesta de Dana. Solo quería completarlo.

DECLARE @names VARCHAR(MAX)
SET @names = ''

SELECT @names = @names + ', ' + Name FROM Names 

-- Deleting last two symbols (', ')
SET @sSql = LEFT(@sSql, LEN(@sSql) - 1)

contestado el 23 de mayo de 17 a las 12:05

Si está eliminando los dos últimos símbolos ',', debe agregar ',' después del Nombre ('SELECT \ @names = \ @names + Name +', 'FROM Names'). De esa forma, los dos últimos caracteres siempre serán ','. - JT_

En mi caso, necesitaba deshacerme del líder coma, así que cambie la consulta a SELECT @names = @names + CASE WHEN LEN(@names)=0 THEN '' ELSE ', ' END + Name FROM Names entonces no tienes que truncarlo después. - Tian van Heerden

Esta respuesta requerirá algunos privilegios en el servidor para funcionar.

asambleas son una buena opción para ti. Hay muchos sitios que explican cómo crearlo. El que creo que está muy bien explicado es este .

Si quieres, ya he creado el ensamblaje y es posible descargar la DLL aquí.

Una vez que lo haya descargado, deberá ejecutar el siguiente script en su servidor SQL:

EXEC sp_configure 'show advanced options', 1
RECONFIGURE;
EXEC sp_configure 'clr strict security', 1;
RECONFIGURE;

CREATE Assembly concat_assembly 
   AUTHORIZATION dbo 
   FROM '<PATH TO Concat.dll IN SERVER>' 
   WITH PERMISSION_SET = SAFE; 
GO 

CREATE AGGREGATE dbo.concat ( 

    @Value NVARCHAR(MAX) 
  , @Delimiter NVARCHAR(4000) 

) RETURNS NVARCHAR(MAX) 
EXTERNAL Name concat_assembly.[Concat.Concat]; 
GO  

sp_configure 'clr enabled', 1;
RECONFIGURE

Observe que el servidor puede acceder a la ruta al ensamblaje. Dado que ha realizado con éxito todos los pasos, puede utilizar la función como:

SELECT dbo.Concat(field1, ',')
FROM Table1

¡¡¡Espero eso ayude!!!


ACTUALIZACIÓN:

Desde MS-SQL 2017 es posible utilizar el STRING_AGG función

Respondido el 30 de Septiembre de 20 a las 01:09

El enlace DLL es un error 404. Usar un ensamblaje para esto es una exageración. Ver la mejor respuesta para SQL Server. - Protiguo

Por lo general, uso seleccionar como este para concatenar cadenas en SQL Server:

with lines as 
( 
  select 
    row_number() over(order by id) id, -- id is a line id
    line -- line of text.
  from
    source -- line source
), 
result_lines as 
( 
  select 
    id, 
    cast(line as nvarchar(max)) line 
  from 
    lines 
  where 
    id = 1 
  union all 
  select 
    l.id, 
    cast(r.line + N', ' + l.line as nvarchar(max))
  from 
    lines l 
    inner join 
    result_lines r 
    on 
      l.id = r.id + 1 
) 
select top 1 
  line
from
  result_lines
order by
  id desc

Respondido 06 Jul 11, 08:07

Si desea lidiar con nulos, puede hacerlo agregando una cláusula where o agregando otra COALESCE alrededor de la primera.

DECLARE @Names VARCHAR(8000) 
SELECT @Names = COALESCE(COALESCE(@Names + ', ', '') + Name, @Names) FROM People

Respondido 27 Jul 11, 21:07

además de la respuesta de Chris Shaffer

si sus datos pueden repetirse como

Tom
Ali
John
Ali
Tom
Mike

En vez de tener Tom,Ali,John,Ali,Tom,Mike

Puede utilizar DISTINCT para evitar duplicados y obtener Tom,Ali,John,Mike

DECLARE @Names VARCHAR(8000) 
SELECT DISTINCT @Names = COALESCE(@Names + ',', '') + Name
FROM People
WHERE Name IS NOT NULL
SELECT @Names

Respondido 16 ago 19, 01:08

En Oracle, es wm_concat. Creo que esta función está disponible en Liberación de 10g y más alto.

Respondido 26 Feb 12, 18:02

Esto también puede ser útil

create table #test (id int,name varchar(10))
--use separate inserts on older versions of SQL Server
insert into #test values (1,'Peter'), (1,'Paul'), (1,'Mary'), (2,'Alex'), (3,'Jack')

DECLARE @t VARCHAR(255)
SELECT @t = ISNULL(@t + ',' + name, name) FROM #test WHERE id = 1
select @t
drop table #test

devoluciones

Peter,Paul,Mary

Respondido 25 Oct 13, 09:10

Desafortunadamente, este comportamiento parece no tener soporte oficial. MSDN dice: "Si se hace referencia a una variable en una lista de selección, debe asignársele un valor escalar o la instrucción SELECT solo debe devolver una fila". Y hay personas que observaron problemas: sqlmag.com/sql-server/multi-row-variable-assignment-and-order - azulado

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.