PIVOT 实现数据库中行列转换

  本文转自:http://www.cnblogs.com/yank/archive/2008/09/09/1287556.html

数据库中行列转换

  PIVOT UNPIVOT 关系运算符将表值表达式更改为另一个表。PIVOT 通过将表达式某一列中的唯一值转换为输出中的多个列来旋转表值表达式,并在必要时对最终输出中所需的任何其余列值执行聚合。 PIVOT 提供的语法比一系列复杂的 SELECT...CASE 语句中所指定的语法更简单和更具可读性。

     在我们进行复杂的查询统计的时候,特别是销售统计、处理大量数据的时候,PIVOT的作用就显得非常突出。

案例分析:在开发一个收集客户资源的小型系统时,需要对客户的资源进行查询统计,本来想用原来的统计解决方案,但是哥们提出了使用Pivot函数,这个我还真没用过,所以就针对这个函数进行了一些学习。

      每一个客户资源通过不同的渠道进来,需要公司成员对用户的信息进行处理,回访、邮件之类的,所以客户信息的状态需要修改,而且需要对每一种状态的客户信息进行统计。如果按照旧的逻辑,采用简单的Count语句去查询统计,SQL语句如下: 

Code
select S.F_status,count(S.F_ID)as F_Count from c2c.dbo.T_Spread_customer as S
group by S.F_status

你得到的结果类似于:

F_status  F_Count
----------- -----------
NULL        4
1             1
4             2
5             1
6             5
7             1

如果是查询整个数据表的统计信息,或许这样做也不是很麻烦,只需要遍历你得到的表,取出数据,然后匹配到某一状态就可以。但是,如果根据客户信息不同来源进行统计,显然这样做,局限性很大,我们没有办法一次性得到各个来源的统计信息。而采用PIVOT,你会得到如下的结果:

F_Num  F_Source F_Total   F_Normal  F_Crm F_Wait   F_InEffect  F_Effect
----------- ------- ----------- ----------- ----------- ----------- ----------- -----------
1            First          3           0               2           0           0           1
2           Second       3           0               0           1           0           2
3           Third          3           0               0           0           1           2
4           Forth         1            1               0           0           0           0
5           Other         0           0               0           0           0           0

它把原来一列的数据,变成了Table的一行数据,而我们要展示给用户的也是这样一张表,所以利用此函数可以节省大量的逻辑代码。方便、快捷、高效。

具体的SQL语句如下: 

select * from 
(
select S.F_status,count(S.F_ID)as F_Count from c2c.dbo.T_Spread_customer as S
group by S.F_status
)
As T 

PIVOT(
sum(T.F_Count) for T.F_Status in([1],[4],[5],[6],[7])) as C

在这里,我对其显示进行一些加工和判定:

加工后的SQL语句
select F_PsnID,isnull([1],0)+isnull([4],0)+isnull([5],0)+isnull([6],0)+isnull([7],0as 'F_Total',isnull([1],0as 'F_Normal',
isnull([4],0as 'F_NormalCrm',isnull([5],0as 'F_Wait',isnull([7],0as 'F_InEffect',isnull([6],0as 'F_Effect'
from (

select S.F_PsnID,S.F_status,count(S.F_ID)as F_Count from c2c.dbo.T_Spread_customer as S
where (1=1)
group by S.F_PsnID,S.F_status

)
As T 

PIVOT(
sum(T.F_Count) for T.F_Status in([1],[4],[5],[6],[7])) as C
order by F_Total desc

当然这只是个简单的小例子,你可以使用PIVOT,然后进行加工处理,它可以实现更为强大的功能。我在应用的时候用到了加入了临时表、分页等功能。

UNPIVOT PIVOT 执行相反的操作,将表值表达式的列转换为列值。但是在实际应用中,有些聚合之后的数据很难进行拆分。所以呢,UNPIVOT并非PIVOT的逆过程。

建议:如果你想了解的更加清楚,请参考: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

 

你可能感兴趣的:(PIVOT 实现数据库中行列转换)