天天看點

單表行轉列

單表行轉列 2008-08-08 13:45

把表 id sid          course result 1 2005001 國文      80.0

     2 2005001 數學      90.0

     3 2005001 英語      80.0

     4 2005002 國文      56.0

     5 2005002 數學      69.0 要将其轉變為:

單表行轉列

可以看得出來,表2列是由表1的行資料轉化而來的,隻有姓名列是表1中的列。 一步一步的來嘛,其他的列難搞,如果表2隻有1列姓名的話,那麼very easy了,不就是一個簡單的分組嘛。 Select 姓名 From 成績表 Group By 姓名 現在sql語句的架子搭起來了,無論以後如何變化,分組是少不了的。 那麼開始下一步,想這個結果集中再添加1列,多了我們不加,因為你不論是能處理國文,還是數學,還是英語列,那麼其他的列隻要原樣照抄就可以了,頂多修改一下參數而已。 從國文列開始吧,這一列的資料都可以從表1中找到,如果我們隻要“國文”這一列,那麼也好寫。 Sql語句疑似: Select 姓名,case when 課程='國文' then 成績 end From 成績表 Group By 姓名 那就F5吧。 嗯,啊,...挂了。 趕緊看錯誤提示: 伺服器: 消息 8120,級别 16,狀态 1,行 1

列 '成績表.成績' 在選擇清單中無效,因為該列既不包含在聚合函數中,也不包含在 GROUP BY 子句中。

伺服器: 消息 8120,級别 16,狀态 1,行 1

列 '成績表.課程' 在選擇清單中無效,因為該列既不包含在聚合函數中,也不包含在 GROUP BY 子句中。 字段成績和課程還必須在聚合函數中或Group By中,如果在Group By中呢?

單表行轉列
資料倒是有了,可是行多了點,看來隻能從聚合入手了。 到底是那個聚合?聚合有max,min,avg,sum,count,max和min首先幹掉,我們不是要最大值,最小值,難道是平均值?難道是個數?難道是求和??? 那就試試呗。 Select 姓名,sum(case when 課程='國文' then 成績 end) From 成績表 Group By 姓名
單表行轉列
嘿,真不錯。 該有的都有了,就是沒列名,好辦,給個别名嘛。 Select 姓名,sum(case when 課程='國文' then 成績 end) As '國文' From 成績表 Group By 姓名
單表行轉列

那麼其他幾列也就好辦了。 充分發揚CVS精神。 Select 姓名,

sum(case when 課程='國文' then 成績 end) As '國文' ,

sum(case when 課程='數學' then 成績 end) As '數學',

sum(case when 課程='英語' then 成績 end) As '英語'

From 成績表 Group By 姓名

單表行轉列

可是結果有NULL,那還不好辦,你的case when then end沒寫完,還有else沒寫呢!

Select 姓名,

sum(case when 課程='國文' then 成績 else 0 end) As '國文' ,

sum(case when 課程='數學' then 成績 else 0 end) As '數學',

sum(case when 課程='英語' then 成績 else 0 end) As '英語'

From 成績表 Group By 姓名

單表行轉列

終于修成正果了。 真的? 當然是假的? 怎麼假? 這不廢話麼!你現在寫的Sql語句隻能支援科目表中隻有國文數學英語,那萬一課程中加了一個叫實體的,那你不得改程式了嗎?! 怎麼辦?涼拌。 也就是說這個Sql語句中有變化的地方在紅字部分: Select 姓名,

sum(case when 課程='國文' then 成績 else 0 end) As '國文' ,

sum(case when 課程='數學' then 成績 else 0 end) As '數學',

sum(case when 課程='英語' then 成績 else 0 end) As '英語'

From 成績表 Group By 姓名 紅字部分要從哪裡來?如果專心看,那麼應該能從中間看出來,哪些個“As '國文'”,哪些個“課程='國文'”,其實是資料表中的值,如果僅僅要查詢“國文,數學,英語”的話,那麼easy啊。 Select 課程 From 成績表 Group By 課程 可是我們要的結果是: sum(case when 課程='國文' then 成績 else 0 end) As '國文' ,

sum(case when 課程='數學' then 成績 else 0 end) As '數學',

sum(case when 課程='英語' then 成績 else 0 end) As '英語'

那不簡單,就是些字元串嘛。 我拼,我拼拼拼。 Select ',sum(case when 課程='''+課程+ ''' then 成績 else 0 end) As '''+課程+'''' From 成績表 Group By 課程 結果為:

單表行轉列

哈哈,隻要将這一段和剛才的Select 姓名拼在一起就可以了。 現在麻煩來了,拼沒有問題。 declare @sql nvarchar(4000) set @sql='Select 姓名 ' Select @[email protected]+',sum(case when 課程='''+課程+ ''' then 成績 else 0 end) As '''+課程+'''' From 成績表 Group By 課程 Print @sql 這一段的結果是: Select 姓名 ,sum(case when 課程='數學' then 成績 else 0 end) As '數學',sum(case when 課程='英語' then 成績 else 0 end) As '英語',sum(case when 課程='國文' then 成績 else 0 end) As '國文' 跟我們的要求比較接近了,還要附加一點東西: Select 姓名 ,sum(case when 課程='數學' then 成績 else 0 end) As '數學',sum(case when 課程='英語' then 成績 else 0 end) As '英語',sum(case when 課程='國文' then 成績 else 0 end) As '國文' From 成績表 Group By 姓名 現在麻煩的是,如何執行這個字元串,現在我們将sql語句放在了 @sql 這個變量中了,怎麼執行? 靈機兩動! SqlServer中有個專門将字元串作為sql語句執行的存儲過程---- sp_executesql。 就是它了。 最終版本: declare @sql nvarchar(4000) set @sql='Select 姓名 ' Select @[email protected]+',sum(case when 課程='''+課程+ ''' then 成績 else 0 end) As '''+課程+'''' From 成績表 Group By 課程 Print @sql set @[email protected]+' From 成績表 Group By 姓名' Print @sql execute sp_executesql @sql 當然課程資訊,不一定會從成績表中擷取,很有可能是一個專門的表格,比如叫“課程表”,那麼就更easy了。 declare @sql nvarchar(4000) set @sql='Select 姓名 ' Select @[email protected]+',sum(case when 課程='''+課程+ ''' then 成績 else 0 end) As '''+課程+'''' From 課程表 Print @sql set @[email protected]+' From 成績表 Group By 姓名' Print @sql execute sp_executesql @sql 例程: Create Table 成績表

(

編号 int identity(1,1),

姓名 varchar(50),

課程 varchar(50),

成績 int

)

Go

Insert Into 成績表(姓名,課程,成績)

Select '張三','國文',55 union

Select '張三','數學',66 union

Select '張三','英語',77 union

Select '李四','國文',88 union

Select '李四','數學',99 union

Select '李四','英語',100 union

Select '王五','國文',44 union

Select '王五','數學',33 union

Select '馬六','英語',22 union

Select '馬六','國文',11

Go

Select * From 成績表

Go

Select 姓名,

'國文'=sum((case when 課程='國文' then 成績 else 0 end)),

'數學'=sum((case 課程 when '數學' then 成績 else 0 end)),

'英語'=sum((case 課程 when '英語' then 成績 else 0 end))

From 成績表

Group By 姓名

Go

Select 姓名,

sum(case when 課程='國文' then 成績 else 0 end) As '國文' ,

sum(case when 課程='數學' then 成績 else 0 end) As '數學',

sum(case when 課程='英語' then 成績 else 0 end) As '英語'

From 成績表 Group By 姓名

Go

declare @sql nvarchar(4000)

set @sql='Select 姓名 '

Select @[email protected]+',sum(case when 課程='''+課程+ ''' then 成績 else 0 end) As '''+課程+''''

From 成績表 Group By 課程

--Print @sql

set @[email protected]+' From 成績表 Group By 姓名'

--Print @sql

execute sp_executesql @sql