在SQLServer 2000環(huán)境中,如果要實現(xiàn)交叉表格報表,主要是靠一系列復雜的 SELECT...CASE 語句.
其實現(xiàn)過程請參閱這里 T-SQL 交叉報表(行列互換) 交叉查詢 旋轉查詢
在SQLServer 2005中我們可以使用PIVOT關系運算符來實現(xiàn)行列轉換.
還是以學生成績表來舉例:
id姓名 科目 成績
1張三語文60
2張三數(shù)學65
3張三外語70
4李四語文80
5李四數(shù)學90
6李四外語85
7王五語文70
8王五數(shù)學71
9王五外語75
10趙六語文64
11趙六數(shù)學67
12趙六外語76
查詢后得出:
姓名語文數(shù)學外語
李四80 90 85
王五70 71 75
張三60 65 70
趙六64 67 76
-- 準備數(shù)據(jù) :
select * from sysobjects where [xtype] = 'u'
go
if exists( select id from sysobjects where name = 'studentscore' )
drop table studentscore -- 刪除與實驗沖突的表
go
create table studentscore -- 創(chuàng)建實驗表
(
[id] int identity ( 1 , 1 ),
[name] nvarchar ( 20 ) not null,
subject nvarchar ( 20 ) not null,
score int not null
)
go
select * from studentscore
go
-- 添加實驗數(shù)據(jù)
insert studentscore values ( ' 張三 ' , ' 語文 ' , '60' );
insert studentscore values ( ' 張三 ' , ' 數(shù)學 ' , '65' );
insert studentscore values ( ' 張三 ' , ' 外語 ' , '70' );
insert studentscore values ( ' 李四 ' , ' 語文 ' , '80' );
insert studentscore values ( ' 李四 ' , ' 數(shù)學 ' , '90' );
insert studentscore values ( ' 李四 ' , ' 外語 ' , '85' );
insert studentscore values ( ' 王五 ' , ' 語文 ' , '70' );
insert studentscore values ( ' 王五 ' , ' 數(shù)學 ' , '71' );
insert studentscore values ( ' 王五 ' , ' 外語 ' , '75' );
insert studentscore values ( ' 趙六 ' , ' 語文 ' , '64' );
insert studentscore values ( ' 趙六 ' , ' 數(shù)學 ' , '67' );
insert studentscore values ( ' 趙六 ' , ' 外語 ' , '76' );
go
select * from studentscore
go
使用 SELECT...CASE 語句實現(xiàn)代碼如下
select [name] ,
語文 = max ( case
when subject = ' 語文 ' then score else 0
end ),
數(shù)學 = max ( case
when subject = ' 數(shù)學 ' then score else 0
end ),
外語 = max ( case
when subject = ' 外語 ' then score else 0
end )
from studentscore
group by [name]
結果:
下面我們使用PIVOT關系運算符來實現(xiàn)行列轉換
select [name] , [ 語文 ] as ' 語文 ' , [ 數(shù)學 ] as ' 數(shù)學 ' , [ 外語 ] as ' 外語 '
from ( select score , subject , [name] from studentscore ) as ss
pivot
(
sum ( score ) for subject in( [ 語文 ] , [ 數(shù)學 ] , [ 外語 ] )
) as pvt
結果:用較少的代碼完成了交叉表格報表
============================
對于這種方法要注意的一點是,我們使用sum()聚合函數(shù),表面上沒有指定按什么方式分組,但是自動按照name列分組了.
怎么做到的呢?原來 pivot關系運算符會根據(jù)前面的對象中的列來自行判斷,在這個例子中 pivot前面的對象是ss,是個子查詢,這個子查詢中只有三列,score , subject 和 [name],但是 pivot運算符內部使用了score 和 subject這兩列,那么肯定是對[name]分組.
所以我們得出, pivot運算符的分組規(guī)則是,跟隨對象中的那些不在 pivot運算符內部的列:
為了好理解我們再寫一個例子:
-- 在 ss 這個子查詢中 , 多加一列 id
-- 那么 pivot 應該按照 name 和 id 進行分組
select [name] , [ 語文 ] as ' 語文 ' , [ 數(shù)學 ] as ' 數(shù)學 ' , [ 外語 ] as ' 外語 '
from ( select score , subject , [name],id from studentscore ) as ss
pivot
(
sum ( score ) for subject in( [ 語文 ] , [ 數(shù)學 ] , [ 外語 ] )
) as pvt
結果:驗證了我們的設想
UNPIVOT關系運算符從字面上來看,就知道它的用途正好和PIVOT相反,下面舉例說明:
if exists( select id from sysobjects where name = 'studentscore' )
drop table studentscore -- 刪除與實驗沖突的表
go
create table studentscore -- 創(chuàng)建實驗表
(
[id] int identity ( 1 , 1 ),
[name] nvarchar ( 20 ) not null,
yuwen int not null,
shuxue int not null,
waiyu int not null
)
go
select * from studentscore
go
-- 添加實驗數(shù)據(jù)
insert studentscore values ( ' 張三 ' , '60' , '65' , '70' );
insert studentscore values ( ' 李四 ' , '80' , '90' , '86' );
insert studentscore values ( ' 王五 ' , '70' , '71' , '75' );
insert studentscore values ( ' 趙六 ' , '64' , '67' , '76' );
go
select * from studentscore
go
結果:
SELECT id , [name] , subject , score
FROM
( SELECT id , [name] , 語文 = yuwen , 數(shù)學 = shuxue , 外語 = waiyu
FROM studentscore ) as ss
UNPIVOT
( score FOR subject IN
( 語文 , 數(shù)學 , 外語 )
) AS unpvt
結果:
更多文章、技術交流、商務合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯(lián)系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
