stuff string_agg group_concat sql sql-server tsql xquery sql-server-group-concat

string_agg - stuff select sql server



Cómo concatenar todas las cadenas de una columna determinada para cada grupo (4)

Supongamos que tengo esta tabla [Table1]

Name Mark ------- ------ ABC 10 DEF 10 GHI 10 JKL 20 MNO 20 PQR 30

¿Cuál debería ser mi declaración SQL para recuperar un registro que se parece a esto: (agrupar por [marca]). He hecho las columnas 1 y 2, pero no sé cómo lograr la tercera columna (concat la [nombre] con la misma [marca])

mark count names ---- ----- ----------- 10 3 ABC,DEF,GHI 20 2 JKL,MNO 30 1 PQR

Estoy usando Microsoft SQL. Por favor ayuda. Gracias


Aquí hay una respuesta relacionada con el rendimiento!

http://jerrytech.blogspot.com/2010/04/tsql-concatenate-strings-1-2-3-and.html

El uso de funciones XML en una consulta grande es un asesino de rendimiento.

Usar un CTE es una superestrella del rendimiento.

Echa un vistazo al enlace, te explicará cómo.

Admito que el trabajo para lograrlo es más.

Pero el resultado es milisegundos en millones de filas.


Basado libremente en Itzik Ben-Gan, Dentro de Microsoft SQL Server 2005: Programación T-SQL , pág. 215:

IF OBJECT_ID(''dbo.Table1'') IS NOT NULL DROP TABLE dbo.Table1 ; GO CREATE TABLE dbo.Table1 ( Name VARCHAR(10), Mark INT ) ; INSERT INTO dbo.Table1 ( Name, Mark ) VALUES ( ''ABC'', 10 ) ; INSERT INTO dbo.Table1 ( Name, Mark ) VALUES ( ''DEF'', 10 ) ; INSERT INTO dbo.Table1 ( Name, Mark ) VALUES ( ''GHI'', 10 ) ; INSERT INTO dbo.Table1 ( Name, Mark ) VALUES ( ''JKL'', 20 ) ; INSERT INTO dbo.Table1 ( Name, Mark ) VALUES ( ''MNO'', 20 ) ; INSERT INTO dbo.Table1 ( Name, Mark ) VALUES ( ''PQR'', 30 ) ; WITH DelimitedNames AS ( SELECT Mark, T2.Count, ( SELECT Name + '','' AS [text()] FROM dbo.Table1 AS T1 WHERE T1.Mark = T2.Mark ORDER BY T1.Mark FOR XML PATH('''')) AS Names FROM ( SELECT Mark, COUNT(*) AS Count FROM dbo.Table1 GROUP BY Mark ) AS T2 ) SELECT Mark, Count, LEFT(Names, LEN(NAMES) - 1) AS Names FROM DelimitedNames ;


La solución de polishchuks es más elegante, pero esto es básicamente lo mismo, solo tratamos la coma final de manera diferente.

CREATE TABLE #Marks(Name nchar(3), Mark int) INSERT INTO #Marks SELECT ''ABC'', 10 UNION ALL SELECT ''DEF'', 10 UNION ALL SELECT ''GHI'', 10 UNION ALL SELECT ''JKL'', 20 UNION ALL SELECT ''MNO'', 20 UNION ALL SELECT ''PQR'', 30 SELECT mark, [count], CASE WHEN Len(Names) > 0 THEN LEFT(Names, LEN(Names) -1) ELSE '''' END names FROM ( SELECT Mark, COUNT(Mark) AS [count], ( SELECT DISTINCT Name + '', '' FROM #Marks M1 WHERE M1.Mark = M2.Mark FOR XML PATH('''') ) Names FROM #Marks M2 GROUP BY Mark ) M


Si MS SQL 2005 o superior.

declare @t table([name] varchar(max), mark int) insert @t values (''ABC'', 10), (''DEF'', 10), (''GHI'', 10), (''JKL'', 20), (''MNO'', 20), (''PQR'', 30) select t.mark, COUNT(*) [count] ,STUFF(( select '','' + [name] from @t t1 where t1.mark = t.mark for xml path(''''), type ).value(''.'', ''varchar(max)''), 1, 1, '''') [values] from @t t group by t.mark

Salida:

mark count values ----------- ----------- -------------- 10 3 ABC,DEF,GHI 20 2 JKL,MNO 30 1 PQR