2013-02-09 6 views
15

Я хотел бы использовать сводный SQL-запрос для построения таблицы результатов, в которой текст конкатенации возникает в разделе DATA сводной таблицы.Sql PIVOT и агрегат конкатенации строк

т.е. у меня есть следующий результат с помощью простого выбора:

 
+------------+-----------------+---------------+ 
| 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 | 
+------------+-----------------+---------------+ 

И я хотел бы построить результат запроса, который будет выглядеть следующим образом:

 
+---------------------+------------------------+------------------------+---------------------------------------+-----------------+-------------------------------------+ 
| 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 | 
+---------------------+------------------------+------------------------+---------------------------------------+-----------------+-------------------------------------+ 

Я знаю, как использовать оператор PIVOT в ms-sql, но я не знаю, как агрегировать имя ресурса в конкатенацию разделенных запятыми элементов для каждого типа ресурса.

P.S Я также мог бы использовать решение с использованием Martix, предоставляемого SSRS 2008-R2, с использованием Report Builde 3 с первой таблицей в качестве моего набора данных и создания матрицы, которая будет агрегировать имена ресурсов в строку, разделенную запятой.

+1

http://stackoverflow.com/questions/10294846/combine-two-tables-in-one-sql См. Этот ответ re: FOR XML PATH – Paul

+1

Доступна функция агрегации CLR Concate, которую вы можете добавить в свою базу данных. Я считаю, что вы могли бы сделать поворот легко сделать это, так как вы просто используете регулярную точку опоры, но вместо того, чтобы использовать совокупный SUM/MAX/и т. Д. вы должны использовать агрегатную функцию Concatenate. Здесь приведен пример совокупной конкатенации, в Интернете есть другие: http://msdn.microsoft.com/en-us/library/ms182741.aspx Это действительно полезная функция. – AaronLS

+0

@AaronLS Спасибо .. это действительно мы полны, но, к сожалению, я не смог создать агрегаты, так как клиент может запускать только простые запросы выбора, и он никогда не получит разрешения на создание нового агрегата CLR. – Mortalus

ответ

13

Для того, чтобы получить результат, сначала вы должны объединить значения в запятую.

Я хотел бы использовать CROSS APPLY и 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) 

См SQL Fiddle with Demo. Дает результат:

| 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 | 

Тогда вы будете применять ваши PIVOT к этому результату:

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 

См SQL Fiddle with Demo.Ваш конечный результат будет тогда:

| 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 | 
2

В построителе отчетов вы должны использовать таблицы или матрицы мастеров и выполните следующие действия:

  • Resource Type поле групп столбцов.
  • Event Name поля в строке группы.
  • И Resource Name поле как детали, вы должны использовать функцию агрегата, такую ​​как Count.

На этом этапе завершите работу мастера, а затем завершите редактирование ячейки Resource Name в качестве выражения. Заменить выражение с:

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

Теперь испытанный:

enter image description here

+1

Этот ответ также абсолютно прав, но, к сожалению, я не мог отметить оба, поэтому я просто голосовал, и на самом деле в моем случае это могло многое помочь. – Mortalus

+0

@ Mortalus. Я ценю ответ. – glh

+1

Вы можете отменить отметку и отметить ответ, если это более подходит;) – glh

0

Полный рабочий пример:

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 
4

Это работает для меня в SQL 2008, и это динамический - будет обрабатывать дополнительные Resource Type

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; 
Смежные вопросы