2013-05-07 3 views
2

У меня есть таблица вроде этого ...Tsql комплекс Pivot

LEVEL  Action   Date    User 
-------------------------------------------------- 
1   Approve  01/01/2013  User1 
2   Approve  02/01/2013  User2 
3   Rejected  03/01/2013  User3 
1   Approve  04/01/2013  User1 
2   Approve  05/01/2013  User2 
3   Approve  06/01/2013  User3 
.    .    .    . 
.    .    .    . 
.    .    .    . 

И я хочу это ...

Возможно ли это с помощью PIVOT?

LEVEL1 - User 1   LEVEL2 - User 2     LEVEL3 - User 3 
--------------------------------------------------------------------------- 
01/01/2013 - Approve  02/01/2013 - Approve    03/01/2013 - Rejected 
04/01/2013 - Approve  05/01/2013 - Approve    06/01/2013 - Approve 
     .      .        . 
     .      .        . 

Примечание: Номер уровня является динамическим. например Это может быть 5 уровней, 6 уровней и т. Д., Чтобы полностью одобрить один элемент. Таким образом, количество столбцов в таблице Pivoted является динамическим.

+1

Для динамического количества столбцов - вам придется использовать динамический SQL. Множество примеров для этого как на этом сайте, так и через intertnet. http://stackoverflow.com/questions/10404348/sql-server-dynamic-pivot-query https://www.simple-talk.com/blogs/2007/09/14/pivots-with-dynamic-columns-in -sql-server-2005/ –

ответ

7

Да, это можно сделать с помощью функции PIVOT. Сначала я хотел бы взглянуть на запрограммированную версию запроса, чтобы вы могли видеть, как этот запрос написан, прежде чем перейти к динамической версии запроса.

Статическая версия будет похожа на следующее:

select [Level1 - User1], [Level2 - User2], [Level3 - User3] 
from 
(
    select 'Level'+cast(level as varchar(1)) + ' - '+ [user] col, 
    convert(varchar(10), date, 101) +' - '+ action value, 
    row_number() over(partition by level order by [user], date) rn 
    from yt 
) d 
pivot 
(
    max(value) 
    for col in ([Level1 - User1], [Level2 - User2], [Level3 - User3]) 
) piv; 

SQL Fiddle with Demo См. Вы заметите, что столбцы level и user объединены для создания новых столбцов, а date и action объединяются для создания значения для каждого столбца. Я также добавил row_number(), чтобы создать уникальное значение для каждой строки, это будет важно, если вы примените функцию aggregate в PIVOT. Если вы не используете это, вы получите только одну строку.

Поскольку теперь у вас есть рабочий вариант, это может быть преобразован в динамический вариант легко:

DECLARE @cols AS NVARCHAR(MAX), 
    @query AS NVARCHAR(MAX) 

select @cols = STUFF((SELECT distinct ',' + QUOTENAME('Level'+cast(level as varchar(1)) + ' - '+ [user]) 
        from yt 
      FOR XML PATH(''), TYPE 
      ).value('.', 'NVARCHAR(MAX)') 
     ,1,1,'') 

set @query = 'SELECT ' + @cols + ' from 
      (
       select ''Level''+cast(level as varchar(1)) + '' - ''+ [user] col, 
        convert(varchar(10), date, 101) +'' - ''+ action value, 
        row_number() over(partition by level order by [user], date) rn 
       from yt 
      ) x 
      pivot 
      (
       max(value) 
       for col in (' + @cols + ') 
      ) p ' 

execute(@query); 

См SQL Fiddle with Demo. Результат для обоих:

|  LEVEL1 - USER1 |  LEVEL2 - USER2 |  LEVEL3 - USER3 | 
----------------------------------------------------------------------- 
| 01/01/2013 - Approve | 02/01/2013 - Approve | 03/01/2013 - Rejected | 
| 04/01/2013 - Approve | 05/01/2013 - Approve | 06/01/2013 - Approve | 
+0

вы слишком хороши, чтобы решать проблемы с поворотным явлением (я видел, что многие из ваших ответов Pivots.), поэтому я подумал, могу ли вы предложить мне хорошую статью для изучения Pivot (откуда вы учитесь) , – Luv

+2

@ Luv Я узнал, отвечая на вопросы здесь! :) – Taryn

+0

Красивая. Позвольте мне попробовать это решение. :) –

Смежные вопросы