首先从SQL Server 的技术资料库中把PIVOT的定义搬了下来,具体网址见(http://technet.microsoft.com/zh-cn/library/ms177410(v=sql.105).aspx)。
以使用 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的功能是sql server2005以后才有的功能,故别在2000上白费功夫。
下面来看看一个列子,统计各商品的月份销售报表,原始表有Orders (orderid,goodsCode,sales,createtime),如下图:
好了,先看原始的统计语句:
select GoodsCode as '商品编号',CONVERT(varchar(7), CreateDate , 120 ) as 月份, sum (Sales) as '总销量' from Orders group by GoodsCode, CONVERT(varchar(7), CreateDate , 120 )
接着进行数据透视,编写查看商品1月份2月份的销售总额:
SELECT GoodsCode as '商品编号', [2012-01] as '1月份', [2012-02] as '2月份' FROM (SELECT GoodsCode, Sales ,CONVERT(varchar(7), CreateDate , 120 ) as 月份 FROM Orders ) AS p PIVOT ( sum(Sales) FOR 月份 IN ([2012-01], [2012-02]) ) AS PivotTable;
Pivot 简化了原来需要一堆Case when 才能实现的功能,语法也简洁明了。缺点:无法实现动态转换。