4

我想要把操縱表格數據變成更具視覺吸引力的格式輸出。這可能是問題的一部分,因爲我想要的可能是針對單獨的報告軟件。當我不想使用聚合時,是否應該使用Pivot將SQL Server 2008行值轉換爲列名稱?

我有一個表,看起來像這樣

teacher student 
---------------------- 
teacher1 Bob 
teacher1 Jim 
teacher2 Sam 
teacher3 Bill 
teacher3 John 
teacher3 Eric 

我想要一個表,看起來是這樣的:

teacher1 teacher2 teacher3 
--------------------------------- 
Bob   Sam   Bill 
Jim   null   John 
null  null   Eric 

所以我嘗試餡所有老師的名字在一個變量,然後使用一個Pivot但由於我必須選擇一個聚合我只能得到MaxMin這樣的學生:

DECLARE @teacherList AS VARCHAR(max) 

SELECT @teacherList = Stuff((SELECT DISTINCT',[' + teacher + ']' 
           FROM myTable 
           FOR xml path('')), 1, 1, '') 

DECLARE @dynamic_pivot_query AS VARCHAR(max) 

SET @dynamic_pivot_query = 'select' + @teacherList + 
'from 
(
    SELECT [teacher],[student] 
    FROM [dbo].[myTable] 
) as S 
Pivot 
(
    MIN([student]) 
    FOR teacher IN (' + @teacherList + ') 
) as P 
' 
EXEC(@dynamic_pivot_query) 

這樣做的結果是:

teacher1 teacher2 teacher3 
--------------------------------- 
Bob   Sam   Bill 

假設如下:

  1. #教師,他們的名字是未知的(可變)
  2. #每名教師的學生是未知的,可能每位教師不同

有沒有辦法做到這一點?

回答

1

你可以用row_number來得到你想要的結果。

SET @dynamic_pivot_query = 'select ' + @teacherList + 
'from 
(
    SELECT [teacher],[student], row_number() over(partition by teacher order by student) as rn 
    FROM [dbo].[myTable] 
) as S 
Pivot 
(
    MIN([student]) 
    FOR teacher IN (' + @teacherList + ') 
) as P 
' 

更新:
要刪除SQL注入漏洞,你應該使用quotename正確引用您的字段列表。

SELECT @teacherList = Stuff((SELECT DISTINCT',' + quotename(teacher) 
           FROM myTable 
           FOR xml path('')), 1, 1, '') 
+1

你還更希望小鮑比表(http://xkcd.com/327/)不會長大成爲老師。這對SQL注入很敏感。 – 2012-04-23 18:45:14

+0

@SteveKass - 感謝您指出。我已經更新了答案。 – 2012-04-24 06:19:46

2

編號

SQL Server需要靜態鍵入。沒有辦法創建動態數量的列或動態列類型(sql_variant除外)。

因此,您的動態SQL解決方案是唯一可能的選擇。

不要讓min/max迷惑你:每個聚合總是會有0或1個項目。語法需要一個聚合的理論正確性,但如果(老師,學生)是唯一的聚合是無所事事。它沒有傷害,也不會改變結果。

該方法正確。其實,我現在在這一分鐘里正在研究相同類型的代碼(這很有趣)。

相關問題