2013-05-07 103 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