在做报表时,经常需要将数据表中的行转列,或者列转行,如果不知道方法,你会觉得通过SQL语句来实现非常难。这里,我将使用pivot和unpivot来实现看似复杂的功能。这个功能在sql2005及以上版本才有。
引用MSDN:
可以使用 PIVOT 和 UNPIVOT 关系运算符将表值表达式更改为另一个表。PIVOT 通过将表达式某一列中的唯一值转换为输出中的多个列来旋转表值表达式,并在必要时对最终输出中所需的任何其余列值执行聚合。UNPIVOT 与 PIVOT 执行相反的操作,将表值表达式的列转换为列值,但是在实际应用中,有些聚合之后的数据很难进行拆分。所以呢,unpivot并非pivot的逆过程。
pivot 提供的语法比一系列复杂的 SELECT...CASE 语句中所指定的语法更简单和更具可读性。
使用SELECT...CASE语句进行行转列的方法见:解析SQL Server中行转列问题
简单的例子如下:
---------行转列
--建表
create table test(编号 int,姓名 varchar(20),季度 int,销售额 int)
insert into test values(1,‘simon‘,1,1000)
insert into test values(1,‘simon‘,2,2000)
insert into test values(1,‘simon‘,3,3000)
insert into test values(1,‘simon‘,4,4000)
insert into test values(2,‘meme‘,1,5000)
insert into test values(2,‘meme‘,2,6000)
insert into test values(2,‘meme‘,3,7000)
insert into test values(2,‘meme‘,4,8000)
--执行普通查询
select * from test
--执行转换查询
select 编号,姓名,
[1] as "一季度",
[2] as "二季度",
[3] as "三季度",
[4] as "四季度",
[5] as "随便1"
from
test
pivot
(
sum(销售额)
for 季度 in
([1],[2],[3],[4],[5])
)
as pvt
--------列转行
--建表
create table test2(编号 int,姓名 varchar(20), 一季度 int, 二季度 int, 三季度 int, 四季度 int)
insert into test2 values(1,‘simon‘,1000,2000,4000,5000)
insert into test2 values(2,‘meme‘,3000,3500,4200,5500)
--执行普通查询
select * from test2
--执行转换查询
select 编号,姓名,季度,销售额
from
test2
unpivot
(
销售额
for 季度 in
(一季度,二季度,三季度,四季度)
)
as unpvt
建议:如果你想了解的更加清楚,请参考:http://technet.microsoft.com/zh-cn/library/ms177410.aspx
注意:对升级到 SQL Server 2005 或更高版本的数据库使用 PIVOT 和 UNPIVOT 时,必须将数据库的兼容级别设置为 90 或更高。
有的SQL Server 2005初始安装时,默认的兼容级别为“80”,这时我们需要将兼容级别进行设置,不然,PIVOT不能正常的执行。我在使用PIVOT时就遇到这样的问题。
具体的修改方案如下:
修改兼容级别步骤
1、连接到相应的 SQL Server 数据库引擎实例之后,在对象资源管理器中,单击服务器名称以展开服务器树。
2、展开“数据库”,然后根据数据库的不同,选择用户数据库,或展开“系统数据库”,再选择系统数据库。
3、右键单击数据库,再单击“属性”。
4、在“数据库属性”对话框中,单击“选项”,将会看到“兼容级别”列表框中。
5、若要更改兼容级别,请从列表中选择其他选项。
可用选项包括 SQL Server 2000 (80)、SQL Server 2005 (90) 或 SQL Server 2008 (100)。
具体的兼容级别之间的差异请参考:http://technet.microsoft.com/zh-cn/library/bb510680.aspx