SQLServer 2005 实现交叉表格报表的利器 PIVOT

系统 1800 0

在SQLServer 2000环境中,如果要实现交叉表格报表,主要是靠一系列复杂的 SELECT...CASE 语句.

其实现过程请参阅这里 T-SQL 交叉报表(行列互换) 交叉查询 旋转查询

在SQLServer 2005中我们可以使用PIVOT关系运算符来实现行列转换.

还是以学生成绩表来举例:

id姓名 科目 成绩

1张三语文60
2张三数学65
3张三外语70
4李四语文80
5李四数学90
6李四外语85
7王五语文70
8王五数学71
9王五外语75
10赵六语文64
11赵六数学67
12赵六外语76

查询后得出:

姓名语文数学外语

李四80 90 85
王五70 71 75
张三60 65 70
赵六64 67 76

-- 准备数据 :

select * from sysobjects where [xtype] = 'u'

go

if exists( select id from sysobjects where name = 'studentscore' )

drop table studentscore -- 删除与实验冲突的表

go

create table studentscore -- 创建实验表

(

[id] int identity ( 1 , 1 ),

[name] nvarchar ( 20 ) not null,

subject nvarchar ( 20 ) not null,

score int not null

)

go

select * from studentscore

go

-- 添加实验数据

insert studentscore values ( ' 张三 ' , ' 语文 ' , '60' );

insert studentscore values ( ' 张三 ' , ' 数学 ' , '65' );

insert studentscore values ( ' 张三 ' , ' 外语 ' , '70' );

insert studentscore values ( ' 李四 ' , ' 语文 ' , '80' );

insert studentscore values ( ' 李四 ' , ' 数学 ' , '90' );

insert studentscore values ( ' 李四 ' , ' 外语 ' , '85' );

insert studentscore values ( ' 王五 ' , ' 语文 ' , '70' );

insert studentscore values ( ' 王五 ' , ' 数学 ' , '71' );

insert studentscore values ( ' 王五 ' , ' 外语 ' , '75' );

insert studentscore values ( ' 赵六 ' , ' 语文 ' , '64' );

insert studentscore values ( ' 赵六 ' , ' 数学 ' , '67' );

insert studentscore values ( ' 赵六 ' , ' 外语 ' , '76' );

go

select * from studentscore

go

添加数据后的结果

使用 SELECT...CASE 语句实现代码如下

select [name] ,

语文 = max ( case

when subject = ' 语文 ' then score else 0

end ),

数学 = max ( case

when subject = ' 数学 ' then score else 0

end ),

外语 = max ( case

when subject = ' 外语 ' then score else 0

end )

from studentscore

group by [name]

结果:

下面我们使用PIVOT关系运算符来实现行列转换

select [name] , [ 语文 ] as ' 语文 ' , [ 数学 ] as ' 数学 ' , [ 外语 ] as ' 外语 '

from ( select score , subject , [name] from studentscore ) as ss

pivot

(

sum ( score ) for subject in( [ 语文 ] , [ 数学 ] , [ 外语 ] )

) as pvt

结果:用较少的代码完成了交叉表格报表

============================

对于这种方法要注意的一点是,我们使用sum()聚合函数,表面上没有指定按什么方式分组,但是自动按照name列分组了.

怎么做到的呢?原来 pivot关系运算符会根据前面的对象中的列来自行判断,在这个例子中 pivot前面的对象是ss,是个子查询,这个子查询中只有三列,score , subject [name],但是 pivot运算符内部使用了score subject这两列,那么肯定是对[name]分组.

所以我们得出, pivot运算符的分组规则是,跟随对象中的那些不在 pivot运算符内部的列:

为了好理解我们再写一个例子:

-- ss 这个子查询中 , 多加一列 id

-- 那么 pivot 应该按照 name id 进行分组

select [name] , [ 语文 ] as ' 语文 ' , [ 数学 ] as ' 数学 ' , [ 外语 ] as ' 外语 '

from ( select score , subject , [name],id from studentscore ) as ss

pivot

(

sum ( score ) for subject in( [ 语文 ] , [ 数学 ] , [ 外语 ] )

) as pvt

结果:验证了我们的设想

UNPIVOT关系运算符从字面上来看,就知道它的用途正好和PIVOT相反,下面举例说明:

if exists( select id from sysobjects where name = 'studentscore' )

drop table studentscore -- 删除与实验冲突的表

go

create table studentscore -- 创建实验表

(

[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

-- 添加实验数据

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

结果:

SQLServer 2005 实现交叉表格报表的利器 PIVOT 和 UNPIVOT 关系运算符

SELECT id , [name] , subject , score

FROM

( SELECT id , [name] , 语文 = yuwen , 数学 = shuxue , 外语 = waiyu

FROM studentscore ) as ss

UNPIVOT

( score FOR subject IN

( 语文 , 数学 , 外语 )

) AS unpvt

结果:

SQLServer 2005 实现交叉表格报表的利器 PIVOT 和 UNPIVOT 关系运算符

SQLServer 2005 实现交叉表格报表的利器 PIVOT 和 UNPIVOT 关系运算符


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论