例一:
在sql Server的帮助文档中,对Pivot函数是这样解释的:
可以使用 PIVOT 和 UNPIVOT 关系运算符对表值表达式进行操作以获得另一个表。PIVOT 通过将表达式某一列中的唯一值转换为输出中的多个列来转换表值表达式,并在必要时对最终输出中所需的任何其余的列值执行聚合.
对第一次使用PIVOT函数的朋友来说,这样的解释很难让大家理解,下面编辑用PIVOT函数来实现一个行转列的功能,以便让读者更容易理解该函数.
注意:PIVOT是sql Server2005的新函数,2005前行转列请参看本站:
sqlServer中(行列转换)行转列及列转行且加平均值及汇总值
先创建一个工资表:
Create Table Salary
(
HrName varchar(50),
Monthly varchar(50),
Money money
)
往表中插入数据:
insert into Salary(HrName,Monthly,[Money])
select '张三','一月','3000'
union all
select '张三','二月','3200'
union all
select '张三','三月','3500'
union all
select '李四','3800'
union all
select '李四','4200'
union all
select '李四','3900'
union all
select '张三','2000'
查看正常的数据:
select * from Salary
结果:
HrName Monthly Money
张三 一月 3000.00
张三 二月 3200.00
张三 三月 3500.00
李四 一月 3800.00
李四 二月 4200.00
李四 三月 3900.00
张三 一月 2000.00
查看行转列后的数据:
select HrName as '姓名',[一月],[二月],[三月] from Salary
pivot(sum([Money]) for Monthly in ([一月],[三月])) as pvt
姓名 一月 二月 三月
李四 3800.00 4200.00 3900.00
张三 5000.00 3200.00 500.00
注意:
pivot(sum([Money]) for Monthly in ([一月],[三月])) 中的sum([Money]),这里必须是聚合函数,比如是min,max等。
in ([一月],[三月])中的[一月],[三月]即为Monthly的Value,又为新结果集的列名.
如果我们将其中的一月改为四月,因为数据源中没有四月的记录,所以四月查询出来应该为Null.
测试:
姓名 四月 二月 三月
李四 NULL 4200.00 3900.00
张三 NULL 3200.00 3500.00
例二:
在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--删除与实验冲突的表
create table studentscore--创建实验表
(
[id] int identity(1,1),
[name] nvarchar(20) not null,sans-serif; font-size:14px; line-height:25px"> subject nvarchar(20) not null,sans-serif; font-size:14px; line-height:25px"> score int not null
)
select * from studentscore
--添加实验数据
insert studentscore values ('张三','语文','60');
ottom:0px; color:rgb(51,'数学','65');
ottom:0px; color:rgb(51,'外语','70');
insert studentscore values ('李四','80');
ottom:0px; color:rgb(51,'90');
ottom:0px; color:rgb(51,'85');
insert studentscore values ('王五','71');
ottom:0px; color:rgb(51,'75');
insert studentscore values ('赵六','64');
ottom:0px; color:rgb(51,'67');
ottom:0px; color:rgb(51,'76');
使用 SELECT...CASE 语句实现代码如下
select [name],sans-serif; font-size:14px; line-height:25px"> 语文=max(case
when subject='语文' then score else 0
end),
数学=max(case
when subject='数学' then score else 0
外语=max(case
when subject='外语' then score else 0
end)
from studentscore
group by [name]
结果:
下面我们使用PIVOT关系运算符来实现行列转换
ottom:0px; color:rgb(51,[语文] 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],[@H_502_785@语文] as '语文',[@H_502_785@数学] as '数学',[@H_502_785@外语] as '外语'
from (select score,subject,[name],id from studentscore) as ss
sum(score) for subject in([@H_502_785@语文],[@H_502_785@数学],[@H_502_785@外语])
) as pvt
结果:验证了我们的设想
UNPIVOT关系运算符从字面上来看,就知道它的用途正好和PIVOT相反,下面举例说明:
yuwen int not null,sans-serif; font-size:14px; line-height:25px"> shuxue int not null,sans-serif; font-size:14px; line-height:25px"> waiyu int not null
ottom:0px; color:rgb(51,'60','65','80','90','86');
ottom:0px; color:rgb(51,'70','71','64','67',sans-serif; font-size:14px; line-height:25px"> 结果:
SELECT id, [name], score
FROM
(SELECT id,[name], 语文=yuwen, 数学=shuxue, 外语=waiyu
FROM studentscore) as ss
UNPIVOT
(score FOR subject IN
(语文, 数学, 外语)
)AS unpvt
结果:
使用union all 代替unpivot功能
create
table
test(id
int
,
name
varchar
(20), Q1
sql keyword" style="white-space:Nowrap; list-style:none; font-family:Consolas, Q2
sql keyword" style="white-space:Nowrap; list-style:none; font-family:Consolas, Q3
sql keyword" style="white-space:Nowrap; list-style:none; font-family:Consolas, Q4
)
into
test
values
(1,
'a'
sql plain" style="white-space:Nowrap; list-style:none; font-family:Consolas,1000,2000,4000,5000)
sql plain" style="white-space:Nowrap; list-style:none; font-family:Consolas,3000,3500,4200,5500)
id ,
name
sql plain" style="white-space:Nowrap; list-style:none; font-family:Consolas,quarter =
'Q1'
sql plain" style="white-space:Nowrap; list-style:none; font-family:Consolas, profile = Q1
from
test
all
sql plain" style="white-space:Nowrap; list-style:none; font-family:Consolas, profile = Q2
test
sql plain" style="white-space:Nowrap; list-style:none; font-family:Consolas, profile = Q3
test
sql plain" style="white-space:Nowrap; list-style:none; font-family:Consolas, profile = Q4
test
by
sql plain" style="white-space:Nowrap; list-style:none; font-family:Consolas, quarter
test
/*
name
quarter profile
----------- -------------------- ------- -----------
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。