使用 PIVOT 和 UNPIVOT

  使用过SQL Server 2000的人都知道,要想实现行列转换,必须综合利用聚合函数和动态SQL,具体实现起来需要一定的技巧,而在SQL Server 2005中,使用新引进的关键字PIVOT/UNPIVOT,则可以很容易的实现行列转换的需求。

可以使用 PIVOT 和 UNPIVOT 关系运算符将表值表达式更改为另一个表。PIVOT 通过将表达式某一列中的唯一值转换为输出中的多个列来旋转表值表达式,并在必要时对最终输出中所需的任何其余列值执行聚合。UNPIVOT 与 PIVOT 执行相反的操作,将表值表达式的列转换为列值。

注意注意

对升级到 SQL Server 2005 或更高版本的数据库使用 PIVOT 和 UNPIVOT 时,必须将数据库的兼容级别设置为 90 或更高。有关如何设置数据库兼容级别的信息,请参阅 sp_dbcmptlevel (Transact-SQL)

PIVOT 提供的语法比一系列复杂的 SELECT...CASE 语句中所指定的语法更简单和更具可读性。有关 PIVOT 语法的完整说明,请参阅 FROM (Transact-SQL)

以下是带批注的 PIVOT 语法。

SELECT <非透视的列>,
    [第一个透视的列] AS <列名称>,
    [第二个透视的列] AS <列名称>,
    ...
    [最后一个透视的列] AS <列名称>,
FROM
    (<生成数据的 SELECT 查询>)
    AS <源查询的别名>
PIVOT
(
    <聚合函数>(<要聚合的列>)
FOR
[<包含要成为列标题的值的列>]
    IN ( [第一个透视的列], [第二个透视的列],
    ... [最后一个透视的列])
) AS <透视表的别名>
<可选的 ORDER BY 子句>;

重要说明重要提示

如果聚合函数与 PIVOT 一起使用,则计算聚合时将不考虑出现在值列中的任何空值。

UNPIVOT 将与 PIVOT 执行几乎完全相反的操作,将列转换为行。假设以上示例中生成的表在数据库中存储为 pvt,并且您需要将列标识符Emp1Emp2Emp3Emp4 和 Emp5 旋转为对应于特定供应商的行值。这意味着必须标识另外两个列。包含要旋转的列值(Emp1Emp2...)的列将被称为 Employee,将保存当前位于待旋转列下的值的列被称为 Orders。这些列分别对应于 Transact-SQL 定义中的 pivot_column 和 value_column。以下为该查询。

请注意,UNPIVOT 并不完全是 PIVOT 的逆操作。PIVOT 会执行一次聚合,从而将多个可能的行合并为输出中的单个行。而 UNPIVOT 不会重现原始表值表达式的结果,因为行已经被合并了。另外,UNPIVOT 的输入中的空值不会显示在输出中,而在执行 PIVOT 操作之前,输入中可能有原始的空值。

在本文中我们将通过两个简单的例子详细讲解PIVOT/UNPIVOT的用法。

PIVOT的用法:

首先创建测试表,然后插入测试数据  

create table test(id int,name varchar(20),quarter int,profile int) 
insert into test values(1,"a",1,1000)
insert into test values(1,"a",2,2000)
insert into test values(1,"a",3,4000)
insert into test values(1,"a",4,5000)
insert into test values(2,"b",1,3000)
insert into test values(2,"b",2,3500)
insert into test values(2,"b",3,4200)
insert into test values(2,"b",4,5500)

select * from test

id name quarter profile
----------- -------------- ----------- -----------
1 a 11000
1 a 22000
1 a 34000
1 a 45000
2 b 13000
2 b 23500
2 b 34200
2 b 45500
(8 row(s) affected)

使用PIVOT将四个季度的利润转换成横向显示:

select id,name,
[1] as "一季度",
[2] as "二季度",
[3] as "三季度",
[4] as "四季度"
from
test
pivot
(
sum(profile)
for quarter in
([1],[2],[3],[4])
)
as pvt


id name 一季度  二季度  三季度  四季度
-------- --------- ----------- -------- ------- -------
1 a 1000 2000 4000 5000
2 b 3000 3500 4200 5500
(2 row(s) affected)


UNPIVOT的用法:

首先创建测试表,然后插入测试数据  

create table test2(id int,name varchar(20), Q1 int, Q2 int, Q3 int, Q4 int)
insert into test2 values(1,"a",1000,2000,4000,5000)
insert into test2 values(2,"b",3000,3500,4200,5500)

select * from test2

id name Q1 Q2Q3 Q4
-------- ------- --------- --------- -------- --------
1 a 1000 2000 4000 5000
2 b 3000 3500 4200 5500
(2 row(s) affected)

使用UNPIVOT将同一行中四个季度的列数据转换成四行数据:

select id,name,quarter,profile
from
test
unpivot
(
profile
for quarter in
([Q1],[Q2],[Q3],[Q4])
) 
as unpvt

id name quarter profile
----------- ----------- ---------- -----------
1 a Q1 1000
1 a Q22000
1 a Q34000
1 a Q4 5000
2 b Q1 3000
2 b Q2 3500
2 b Q3 4200
2 b Q4 5500
(8 row(s) affected)

http://technet.microsoft.com/zh-cn/library/ms177410.aspx

http://net.zdnet.com.cn/network_security_zone/2008/0322/779653.shtml





  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值