Convierta varias filas en una con coma como separador [duplicar]


Esta pregunta ya tiene una respuesta aquí:

Si emito SELECT username FROM Users obtengo este resultado:

username
--------
Paul
John
Mary

Pero lo que realmente necesito es una fila con todos los valores separados por coma, así:

Paul, John, Mary

¿Cómo hago esto?

Author: rjstelling, 2009-05-20

10 answers

Esto debería funcionar para usted. Probado hasta SQL 2000.

create table #user (username varchar(25))

insert into #user (username) values ('Paul')
insert into #user (username) values ('John')
insert into #user (username) values ('Mary')

declare @tmp varchar(250)
SET @tmp = ''
select @tmp = @tmp + username + ', ' from #user

select SUBSTRING(@tmp, 0, LEN(@tmp))
 71
Author: mwigdahl,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-05-20 12:44:50
 select
   distinct  
    stuff((
        select ',' + u.username
        from users u
        where u.username = username
        order by u.username
        for xml path('')
    ),1,1,'') as userlist
from users
group by username

Tenía un error tipográfico antes, las obras anteriores

 96
Author: Hogan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-11-23 21:00:06

Buena revisión de varios enfoques:

Http://blogs.msmvps.com/robfarley/2007/04/07/coalesce-is-not-the-answer-to-string-concatentation-in-t-sql/

Copia del artículo -

Coalesce no es la respuesta a la concatentación de cadenas en T-SQL He visto muchas publicaciones a lo largo de los años sobre el uso de la función COALESCE para obtener la concatenación de cadenas de trabajo en T-SQL. Este es uno de los ejemplos aquí (tomado de Readifarian Marc Ridey).

DECLARE @categories varchar(200)
SET @categories = NULL

SELECT @categories = COALESCE(@categories + ',','') + Name
FROM Production.ProductCategory

SELECT @categories

Esta consulta puede ser bastante eficaz, pero hay que tener cuidado, y el uso de COALESCE debe entenderse correctamente. UNEN es la versión de ISNULL que puede tomar más de dos parámetros. Devuelve lo primero en la lista de parámetros que no es null. Así que realmente no tiene nada que ver con la concatenación, y el siguiente fragmento de código es exactamente el mismo - sin usar COALESCE:

DECLARE @categories varchar(200)
SET @categories = ''

SELECT @categories = @categories + ',' + Name
FROM Production.ProductCategory

SELECT @categories

Pero la naturaleza desordenada de las bases de datos hace que esto no sea confiable. Toda la razón por la que T-SQL no (yet) have a concatenate function is that this is an aggregate for which the order of elements is important. Usando este método de asignación de variables de concatenación de cadenas, puede encontrar que la respuesta que se devuelve no tiene todos los valores, particularmente si desea que las subcadenas se pongan en un orden particular. Considere lo siguiente, que en mi máquina solo devuelve', Accesorios', cuando quería devolver', Bicicletas,Ropa,Componentes, Accesorios':

DECLARE @categories varchar(200)
SET @categories = NULL

SELECT @categories = COALESCE(@categories + ',','') + Name
FROM Production.ProductCategory
ORDER BY LEN(Name)

SELECT @categories

Far mejor es usar un método que tenga en cuenta el orden, y que se ha incluido en SQL2005 específicamente para el propósito de concatenación de cadenas - PARA XML PATH (")

SELECT ',' + Name
FROM Production.ProductCategory
ORDER BY LEN(Name)
FOR XML PATH('') 

En el post que hice recientemente comparando GROUP BY y DISTINCT al usar subconsultas, demostré el uso de FOR XML PATH("). Echa un vistazo a esto y verás cómo funciona en una subconsulta. La función 'STUFF' solo está ahí para eliminar la coma inicial.

USE tempdb;
GO
CREATE TABLE t1 (id INT, NAME VARCHAR(MAX));
INSERT t1 values (1,'Jamie');
INSERT t1 values (1,'Joe');
INSERT t1 values (1,'John');
INSERT t1 values (2,'Sai');
INSERT t1 values (2,'Sam');
GO

select
    id,
    stuff((
        select ',' + t.[name]
        from t1 t
        where t.id = t1.id
        order by t.[name]
        for xml path('')
    ),1,1,'') as name_csv
from t1
group by id
; 

PARA XML PATH es uno de los solo situaciones en las que se puede usar ORDER BY en una subconsulta. El otro es SUPERIOR. Y cuando se utiliza una columna sin nombre y PARA XML PATH ( " ), obtendrá una concatenación directa, sin etiquetas XML. Esto significa que las cadenas estarán codificadas en HTML, por lo que si está concatenando cadenas que pueden tener el carácter

 36
Author: A-K,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-10-31 20:22:36

Basado en la respuesta de mwigdahls. si también necesita hacer agrupación aquí es cómo conseguir que se vea como

group, csv
'group1', 'paul, john'
'group2', 'mary'

    --drop table #user
create table #user (groupName varchar(25), username varchar(25))

insert into #user (groupname, username) values ('apostles', 'Paul')
insert into #user (groupname, username) values ('apostles', 'John')
insert into #user (groupname, username) values ('family','Mary')


select
    g1.groupname
    , stuff((
        select ', ' + g.username
        from #user g        
        where g.groupName = g1.groupname        
        order by g.username
        for xml path('')
    ),1,2,'') as name_csv
from #user g1
group by g1.groupname
 8
Author: Tom McDonald,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-07-17 14:56:40

Puede usar esta consulta para realizar la tarea anterior:

DECLARE @test NVARCHAR(max)  
SELECT @test = COALESCE(@test + ',', '') + field2 FROM #test
SELECT field2 = @test 

Para detalles y explicación paso a paso visite el siguiente enlace http://oops-solution.blogspot.com/2011/11/sql-server-convert-table-column-data.html

 6
Author: Rashmi Kant,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-11-04 22:22:35
DECLARE @EmployeeList varchar(100)

SELECT @EmployeeList = COALESCE(@EmployeeList + ', ', '') + 
   CAST(Emp_UniqueID AS varchar(5))
FROM SalesCallsEmployees
WHERE SalCal_UniqueID = 1

SELECT @EmployeeList

Fuente: http://www.sqlteam.com/article/using-coalesce-to-build-comma-delimited-string

 5
Author: vinay,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-09-17 10:35:32

Una solución limpia y flexible en MS SQL Server 2005/2008 es crear una función CLR Agregate.

Encontrarás bastantes artículos (con código) en google.

Parece que este artículo te guía a través de todo el proceso usando C#.

 3
Author: Arjan Einbu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-05-20 19:15:54

En SQLite esto es más simple. Creo que hay implementaciones similares para MySQL, MSSql y Orable

CREATE TABLE Beatles (id integer, name string );
INSERT INTO Beatles VALUES (1, "Paul");
INSERT INTO Beatles VALUES (2, "John");
INSERT INTO Beatles VALUES (3, "Ringo");
INSERT INTO Beatles VALUES (4, "George");
SELECT GROUP_CONCAT(name, ',') FROM Beatles;
 2
Author: elcuco,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-02-13 07:41:19

Puedes usar stuff() para convertir filas como valores separados por comas

select
EmployeeID,
stuff((
  SELECT ',' + FPProjectMaster.GroupName 
      FROM     FPProjectInfo AS t INNER JOIN
              FPProjectMaster ON t.ProjectID = FPProjectMaster.ProjectID
      WHERE  (t.EmployeeID = FPProjectInfo.EmployeeID)
              And t.STatusID = 1
              ORDER BY t.ProjectID
       for xml path('')
       ),1,1,'') as name_csv
from FPProjectInfo
group by EmployeeID;

Gracias @AlexKuznetsov por la referencia para obtener esta respuesta.

 1
Author: Ram,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-05-30 10:44:41

Si estás ejecutando esto a través de PHP, ¿qué pasa con esto?

$hQuery = mysql_query("SELECT * FROM users");
while($hRow = mysql_fetch_array($hQuery)) {
    $hOut .= $hRow['username'] . ", ";
}
$hOut = substr($hOut, 0, strlen($hOut) - 1);
echo $hOut;
 -4
Author: James Brooks,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-05-20 12:49:24