stuff one numeros group_concat concatenate concatenar column sql tsql pivot reporting-services reportbuilder3.0

one - stuff sql server



Sql PIVOT y agregado de concatenación de cadenas (4)

Me gustaría utilizar una consulta SQL dinámica para construir una tabla de resultados donde el texto concatenar como resultado dentro de la sección DATOS de la tabla dinámica.

es decir, tengo el siguiente resultado al usar un simple seleccionar:

+------------+-----------------+---------------+ | Event Name | Resource Type | Resource Name | +------------+-----------------+---------------+ | Event 1 | Resource Type 1 | Resource 1 | | Event 1 | Resource Type 1 | Resource 2 | | Event 1 | Resource Type 2 | Resource 3 | | Event 1 | Resource Type 2 | Resource 4 | | Event 1 | Resource Type 3 | Resource 5 | | Event 1 | Resource Type 3 | Resource 6 | | Event 1 | Resource Type 3 | Resource 7 | | Event 1 | Resource Type 4 | Resource 8 | | Event 2 | Resource Type 5 | Resource 1 | | Event 2 | Resource Type 2 | Resource 3 | | Event 2 | Resource Type 3 | Resource 11 | | Event 2 | Resource Type 3 | Resource 12 | | Event 2 | Resource Type 3 | Resource 13 | | Event 2 | Resource Type 4 | Resource 14 | | Event 2 | Resource Type 5 | Resource 9 | | Event 2 | Resource Type 5 | Resource 16 | +------------+-----------------+---------------+

Y me gustaría construir una consulta de resultados que se vería así:

+---------------------+------------------------+------------------------+---------------------------------------+-----------------+-------------------------------------+ | Event/Resource Type | Resource Type 1 | Resource Type 2 | Resource Type 3 | Resource Type 4 | Resource Type 5 | +---------------------+------------------------+------------------------+---------------------------------------+-----------------+-------------------------------------+ | Event 1 | Resource 1, Resource 2 | Resource 3, Resource 4 | Resource 5, Resource 6, Resource 7 | Resource 8 | NULL | | Event 2 | NULL | Resource 3 | Resource 11, Resource 12, Resource 13 | Resource 14 | Resource 1, Resource 9, Resource 16 | +---------------------+------------------------+------------------------+---------------------------------------+-----------------+-------------------------------------+

Sé cómo usar una instrucción PIVOT en ms-sql, pero no sé cómo agregar el Nombre del recurso en una concatenación de elementos separados por comas para cada tipo de recurso.

PD: También podría usar una solución usando el Martix provisto por SSRS 2008-R2 usando Report Builde 3 con la primera tabla como mi conjunto de datos y crear una matriz que agregue los nombres de los recursos en una cadena separada por comas.


En el generador de informes, debe usar el asistente Tabla o Matriz y hacer lo siguiente:

  • Resource Type campo como grupos de columnas.
  • Event Name campo como los grupos de fila.
  • Y el campo Resource Name como detalles, tendrá que usar una función agregada como Count .

En esta etapa, complete el asistente y, una vez completado, edite la celda Resource Name del Resource Name como una expresión. Reemplaza la expresión con:

=Join( LookupSet( Fields!EVENT_NAME.Value + Fields!RESOURCE_TYPE.Value, Fields!EVENT_NAME.Value + Fields!RESOURCE_TYPE.Value, Fields!RESOURCE_NAME.Value, "DataSet1"), ", ")

Ahora probado y probado:


Ejemplo completo de trabajo:

SET NOCOUNT ON GO DECLARE @SourceTable TABLE ( EventName NVARCHAR(10) ,ResourceType NVARCHAR(20) ,ResourceName NVARCHAR(20) ) INSERT INTO @SourceTable(EventName,ResourceType,ResourceName) VALUES (''Event 1'',''Resource Type 1'',''Resource 1'') ,(''Event 1'',''Resource Type 1'',''Resource 2'') ,(''Event 1'',''Resource Type 2'',''Resource 3'') ,(''Event 1'',''Resource Type 2'',''Resource 4'') ,(''Event 1'',''Resource Type 3'',''Resource 5'') ,(''Event 1'',''Resource Type 3'',''Resource 6'') ,(''Event 1'',''Resource Type 3'',''Resource 7'') ,(''Event 1'',''Resource Type 4'',''Resource 8'') ,(''Event 2'',''Resource Type 5'',''Resource 1'') ,(''Event 2'',''Resource Type 2'',''Resource 3'') ,(''Event 2'',''Resource Type 3'',''Resource 11'') ,(''Event 2'',''Resource Type 3'',''Resource 12'') ,(''Event 2'',''Resource Type 3'',''Resource 13'') ,(''Event 2'',''Resource Type 4'',''Resource 14'') ,(''Event 2'',''Resource Type 5'',''Resource 9'') ,(''Event 2'',''Resource Type 5'',''Resource 16'') ;WITH SourceTable AS ( SELECT DISTINCT ST1.EventName ,ST1.ResourceType ,(SELECT SUBSTRING((SELECT '','' +ResourceName FROM @SourceTable AS ST2 WHERE ST1.EventName=ST2.EventName AND ST1.ResourceType=ST2.ResourceType FOR XML PATH('''')),2,200) AS CSV) AS ResourceName FROM @SourceTable AS ST1 ) SELECT EventName ,[Resource Type 1] ,[Resource Type 2] ,[Resource Type 3] ,[Resource Type 4] ,[Resource Type 5] FROM ( SELECT EventName ,ResourceType ,ResourceName FROM SourceTable ) PivotSource PIVOT ( MAX(ResourceName) FOR ResourceType IN ([Resource Type 1],[Resource Type 2],[Resource Type 3],[Resource Type 4],[Resource Type 5]) ) PivotTable SET NOCOUNT OFF GO


Esto funciona para mí en SQL 2008, y es dinámico; manejará un Resource Type adicional

Working SQLFiddle

IF OBJECT_ID(''tempdb..#test'') IS NOT NULL DROP TABLE #test GO CREATE TABLE #test ( eventName VARCHAR(30), resourceType VARCHAR(30), resourceName VARCHAR(30) ); INSERT INTO #test VALUES (''Event 1'',''Resource Type 1'',''Resource 1''), (''Event 1'',''Resource Type 1'',''Resource 2''), (''Event 1'',''Resource Type 2'',''Resource 3''), (''Event 1'',''Resource Type 2'',''Resource 4''), (''Event 1'',''Resource Type 3'',''Resource 5''), (''Event 1'',''Resource Type 3'',''Resource 6''), (''Event 1'',''Resource Type 3'',''Resource 7''), (''Event 1'',''Resource Type 4'',''Resource 8''), (''Event 2'',''Resource Type 5'',''Resource 1''), (''Event 2'',''Resource Type 2'',''Resource 3''), (''Event 2'',''Resource Type 3'',''Resource 11''), (''Event 2'',''Resource Type 3'',''Resource 12''), (''Event 2'',''Resource Type 3'',''Resource 13''), (''Event 2'',''Resource Type 4'',''Resource 14''), (''Event 2'',''Resource Type 5'',''Resource 9''), (''Event 2'',''Resource Type 5'',''Resource 16''); DECLARE @resourceTypes VARCHAR(max); SELECT @resourceTypes = stuff((SELECT DISTINCT '',['' + resourceType + '']'' FROM #test FOR xml path('''')), 1, 1, ''''); DECLARE @query NVARCHAR(max); SET @query = ''SELECT * FROM (SELECT eventName, resourceType, stuff((SELECT '''','''' + resourceName + '''''''' FROM #test b WHERE a.eventName = b.eventName AND a.resourceType = b.resourceType FOR xml path('''''''')), 1, 1, '''''''') resourceName FROM #test a GROUP BY eventName, resourceType) AS data PIVOT (max(resourceName) FOR resourceType IN ('' + @resourceTypes + '')) AS pvt''; EXEC(@query); DROP TABLE #test;


Para obtener el resultado, primero debe concatenar los valores en la lista separada por comas.

Yo usaría CROSS APPLY y FOR XML PATH :

SELECT distinct e.[Event Name], e.[Resource Type], LEFT(r.ResourceName , LEN(r.ResourceName)-1) ResourceName FROM yourtable e CROSS APPLY ( SELECT r.[Resource Name] + '', '' FROM yourtable r where e.[Event Name] = r.[Event Name] and e.[Resource Type] = r.[Resource Type] FOR XML PATH('''') ) r (ResourceName)

Ver SQL Fiddle con demostración . El te da resultado:

| EVENT NAME | RESOURCE TYPE | RESOURCENAME | ------------------------------------------------------------------------ | Event 1 | Resource Type 1 | Resource 1, Resource 2 | | Event 1 | Resource Type 2 | Resource 3, Resource 4 | | Event 1 | Resource Type 3 | Resource 5, Resource 6, Resource 7 | | Event 1 | Resource Type 4 | Resource 8 | | Event 2 | Resource Type 2 | Resource 3 | | Event 2 | Resource Type 3 | Resource 11, Resource 12, Resource 13 | | Event 2 | Resource Type 4 | Resource 14 | | Event 2 | Resource Type 5 | Resource 1, Resource 9, Resource 16 |

Luego aplicará su PIVOT a este resultado:

SELECT [Event Name], [Resource Type 1], [Resource Type 2], [Resource Type 3], [Resource Type 4], [Resource Type 5] FROM ( SELECT distinct e.[Event Name], e.[Resource Type], LEFT(r.ResourceName , LEN(r.ResourceName)-1) ResourceName FROM yourtable e CROSS APPLY ( SELECT r.[Resource Name] + '', '' FROM yourtable r where e.[Event Name] = r.[Event Name] and e.[Resource Type] = r.[Resource Type] FOR XML PATH('''') ) r (ResourceName) ) src pivot ( max(ResourceName) for [Resource Type] in ([Resource Type 1], [Resource Type 2], [Resource Type 3], [Resource Type 4], [Resource Type 5]) ) piv

Ver SQL Fiddle con demostración . Su resultado final será:

| EVENT NAME | RESOURCE TYPE 1 | RESOURCE TYPE 2 | RESOURCE TYPE 3 | RESOURCE TYPE 4 | RESOURCE TYPE 5 | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | Event 1 | Resource 1, Resource 2 | Resource 3, Resource 4 | Resource 5, Resource 6, Resource 7 | Resource 8 | (null) | | Event 2 | (null) | Resource 3 | Resource 11, Resource 12, Resource 13 | Resource 14 | Resource 1, Resource 9, Resource 16 |