2013-05-07 109 views
2

我有一个这样的表...TSQL复合枢纽

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。在这个网站和整个互联网上都有很多例子。 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/ – 2013-05-07 11:27:57

回答

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。您会注意到leveluser列被连接在一起以创建新列,并且连接dateaction以创建每列的值。我还添加了一个row_number()为每行创建一个唯一值,当您在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

你太善于解决数据透视问题了(我已经看到很多你的Pivot答案)。所以我想如果你能为我提供一篇关于学习Pivot的好文章(从你学习的地方) 。 – Luv 2013-05-07 11:36:52

+2

@Luv我通过回答这里的问题来学习! :) – Taryn 2013-05-07 11:40:18

+0

美丽。让我试试这个解决方案。 :) – 2013-05-07 11:45:19