SQL server 2005 PIVOT运算符的使用

原文:SQL server 2005 PIVOT运算符的使用

PIVOT,UNPIVOT运算符是SQL server 2005支持的新功能之一,主要用来实现行到列的转换。本文主要介绍PIVOT运算符的操作,以及如何实现动态PIVOT的行列转换。

关于UNPIVOT及SQL server 2000下的行列转换请参照本人的其它文章。

一、PIVOT的语法
SELECT
  [non-pivoted column], -- optional
  [additional non-pivoted columns], -- optional
  [first pivoted column],
  [additional pivoted columns]
FROM (
  SELECT query producing sql data for pivot
  -- select pivot columns as dimensions and
  -- value columns as measures from sql tables
) AS TableAlias
PIVOT
( 

  <aggregation function>(column for aggregation or measure column) -- MIN,MAX,SUM,etc 

  FOR []
  IN (
    [first pivoted column], ..., [last pivoted column]
  )
) AS PivotTableAlias
ORDER BY clause – optional

二、PIVOT的使用例子

1. 静态PIVOT的用法

为演示,从NorthWind数据库中提取一些记录生成新的Orders表,然后使用PIVOT将行转换到列。

USE tempdb
GO
SELECT YEAR(OrderDate) AS [Year]
       ,CustomerID
       ,od.Quantity
INTO dbo.Orders
FROM NorthWind..Orders AS o
    JOIN NorthWind..[Order Details] AS od
        ON o.OrderID = od.OrderID
WHERE o.CustomerID IN (‘BONAP‘,‘BOTTM‘,‘ANTON‘)
SELECT CustomerID
	,[1996],[1997],[1998]
FROM dbo.Orders
PIVOT (
	   SUM(Quantity)
	   FOR [Year] IN ([1996],[1997],[1998])
   )x
/*
TSQL中pivot的结构:
    ●  用于生成pivot数据源的源表,作为一个输入表
    ●  pivot表
    ●  聚合列及透视列的选择

TSQL中pivot的实现:
1->上例中Orders表相当于是一个输入表。包含了CustomerID,[Year],Quantity 三个列。
   Year是透视列,用于生成维度。
   pivot首先将聚合列之外的列进行分组,并对其实现聚合。本列中则是对聚合列Quantity之外的列先实现分组,
   即对CustomerID,Year进行分组,并对其Quantity实现聚合,相当于先做如下处理:
*/
SELECT CustomerID
       ,[Year]
       ,SUM(Quantity) AS Total
FROM dbo.Orders
GROUP BY CustomerID
       ,[Year]
ORDER BY CustomerID			   

/*	Result:
CustomerID Year        Total
---------- ----------- -----------
ANTON      1996        24
ANTON      1997        295
ANTON      1998        40
BONAP      1996        181
BONAP      1997        486
BONAP      1998        313
BOTTM      1996        81
BOTTM      1997        454
BOTTM      1998        421
*/
/*
2->pivot根据FOR [Year] IN子句中的值,在结果集中来建立对应的新列,本例中即是列,,
   对于新列,,中的取值,取中间结果集中与之相对应的值。
   如对于客户ANTON,1996列中的值就选择中间结果中对应的Total值,同理列中为。
   并将中间结果pivot表命名为x。

3->最外层的SELECT语句从pivot表生成最终结果,此处因Orders表仅有列,故直接将结果用一个SELECT返回,有嵌套的SELECT参照下例。

--结果:
CustomerID 1996        1997        1998
---------- ----------- ----------- -----------
ANTON      24          295         40
BONAP      181         486         313
BOTTM      81          454         421
*/         以下是为输入表多于一列的例子,数据来源于SQL server 2005的AdventureWorks,其实现的原理同上。
SELECT *
FROM(
	SELECT YEAR(DueDate) [Year]
		   ,CASE MONTH(DueDate)
			WHEN 1 THEN ‘January‘
			WHEN 2 THEN ‘February‘
			WHEN 3 THEN ‘March‘
			WHEN 4 THEN ‘April‘
			WHEN 5 THEN ‘May‘
			WHEN 6 THEN ‘June‘
			WHEN 7 THEN ‘July‘
			WHEN 8 THEN ‘August‘
			WHEN 9 THEN ‘September‘
			WHEN 10 THEN ‘October‘
			WHEN 11 THEN ‘November‘
			WHEN 12 THEN ‘December‘
		   END as [Month]
		   ,ProductID
		   ,OrderQty
	FROM Production.WorkOrder
)WorkOrder
    PIVOT (
           SUM(OrderQty)
           FOR [Month] IN ([January],[February],[March],[April],[May],[June],[July],[August],[September],[October],[November],[December])
          )x
ORDER BY [Year], ProductID
--Result: 末尾部分省略
/*
Year        ProductID   January     February    March       April       May         June        July        August
----------- ----------- ----------- ----------- ----------- ----------- ----------- ----------- ----------- -----------
2002        3           8480        16870       12960       9530        19390       14170       26200       35870
2002        316         1842        3704        2910        2252        4738        3496        7624        10778
2002        324         1842        3704        2910        2252        4738        3496        7546        10600
2002        327         921         1852        1455        1126        2369        1748        3773        5300
2002        328         414         1048        872         458         1272        992         1786        2632
*/

2. 动态PIVOT的使用

USE AdventureWorks;
GO 

--第一种生成透视列的方法,使用了COALESCE来联接字符串
DECLARE @PivotColHeader VARCHAR(MAX)
SELECT @PivotColHeader =
    COALESCE(@PivotColHeader + ‘,[‘ + cast(Name as varchar) + ‘]‘,
    ‘[‘ + cast(Name as varchar) + ‘]‘)   --示例中Name转换为varchar或char类型,注意:在CAST 和CONVERT 中使用varchar 时,显示n的默认值为30
FROM Sales.SalesTerritory
GROUP BY Name

/*
--第二种生成透视列的方法,使用了FOR XML PATH方法
SELECT @PivotColHeader =
    STUFF(
    (
          SELECT DISTINCT ‘,[‘ + cast(Name as varchar) + ‘]‘
          FROM Sales.SalesTerritory
          FOR XML PATH(‘‘)
    ),
    1,1,‘‘)
*/

DECLARE @PivotTableSQL NVARCHAR(MAX)
SET @PivotTableSQL = N‘
    SELECT *
    FROM (
        SELECT YEAR(H.OrderDate) [Year]
			,T.Name
			,H.TotalDue
        FROM Sales.SalesOrderHeader H
			LEFT JOIN Sales.SalesTerritory T
			    ON H.TerritoryID = T.TerritoryID
    )AS PivotData
        PIVOT(
            SUM(TotalDue)
            FOR Name IN (
                         ‘ + @PivotColHeader + ‘
                         )
               ) AS x ‘
EXECUTE sp_executesql @PivotTableSQL    

--Result:部分结果省略
/*
Year        Australia             Canada                Central               France                Germany               Northeast
----------- --------------------- --------------------- --------------------- --------------------- --------------------- ---------------------
2001        1446497.1744          2173647.1453          1263884.1024          199531.723            262752.4184           754833.2045
2002        2380484.8387          7215430.5017          3518185.4756          1717145.7439          575960.0974           3275322.1694
2003        4547123.2777          8186021.9178          4015356.874           4366078.3475          2714826.4297          3833030.25
2004        3823410.2386          3926712.8926          1771532.7396          2853948.6596          2386224.5508          1406555.6861         

*/

对该动态pivot增加汇总列

DECLARE @PivotColHeader VARCHAR(MAX)
DECLARE @TotalCol VARCHAR(MAX)

SELECT @PivotColHeader =                              --使用COALESCE函数生成列标题
    COALESCE(@PivotColHeader + ‘,[‘ + cast(Name as varchar) + ‘]‘,
    ‘[‘ + cast(Name as varchar) + ‘]‘)
    ,
    @TotalCol = COALESCE(@TotalCol + ‘, SUM([‘ + cast(Name as varchar) + ‘]) AS [‘ + cast(Name as varchar) + ‘]‘
     ,‘SUM([‘ + cast(Name as varchar) + ‘]) AS [‘ + cast(Name as varchar) + ‘]‘)     --使用COALESCE函数生成汇总字符串
FROM Sales.SalesTerritory

DECLARE @PivotTableSQL NVARCHAR(MAX)
SET @PivotTableSQL = N‘
    SELECT *
    FROM (
        SELECT CAST(YEAR(H.OrderDate) AS CHAR(4)) [Year]
		,T.Name
		,H.TotalDue
        FROM Sales.SalesOrderHeader H
		LEFT JOIN Sales.SalesTerritory T
		   ON H.TerritoryID = T.TerritoryID
    )AS PivotData
		PIVOT(
			SUM(TotalDue)
			FOR Name IN (
			 ‘ + @PivotColHeader + ‘
				   )
		    ) AS x
    UNION
    SELECT ‘‘GrandTotal‘‘, ‘ + @TotalCol + ‘
    FROM (
	SELECT CAST(YEAR(H.OrderDate) AS CHAR(4)) [Year]
		,T.Name
		,H.TotalDue
	FROM Sales.SalesOrderHeader H
	    LEFT JOIN Sales.SalesTerritory T
		ON H.TerritoryID = T.TerritoryID
	) AS PivotData
		PIVOT(
			SUM(TotalDue)
			FOR Name IN (
				‘ + @PivotColHeader + ‘
				   )
		     ) AS y ‘
--PRINT  @PivotTableSQL
EXECUTE sp_executesql @PivotTableSQL 

--Result:部分结果省略
/*
Year       Australia             Canada                Central               France                Germany               Northeast             Northwest
---------- --------------------- --------------------- --------------------- --------------------- --------------------- --------------------- ---------------------
2001       1446497.1744          2173647.1453          1263884.1024          199531.723            262752.4184           754833.2045           2703481.7947
2002       2380484.8387          7215430.5017          3518185.4756          1717145.7439          575960.0974           3275322.1694          5651688.6685
2003       4547123.2777          8186021.9178          4015356.874           4366078.3475          2714826.4297          3833030.25            7494658.0357
2004       3823410.2386          3926712.8926          1771532.7396          2853948.6596          2386224.5508          1406555.6861          4952772.2793
GrandTotal 12197515.5294         21501812.4574         10568959.1916         9136704.474           5939763.4963          9269741.31            20802600.7782
*/

生成汇总列的注意事项;

1->使用COALESCE函数生成列标题 。

2->使用COALESCE函数生成带有SUM求和函数并且指定了别名的字符串。

3->使用UNION对两个SELECT来实现联接。且将[Year]转换为字符串,因为YEAR(H.OrderDate)得值为 INT ,而‘‘GrandTotal‘‘为字符串,UNION 或UNION ALL使用时必须列的数量和类型相对应。

时间: 2024-10-03 15:01:35

SQL server 2005 PIVOT运算符的使用的相关文章

SQL Server里PIVOT运算符的”红颜祸水“

在今天的文章里我想讨论下SQL Server里一个特别的T-SQL语言结构——自SQL Server 2005引入的PIVOT运算符.我经常引用这个与语言结构是SQL Server里最危险的一个——很快你就会知道为什么.在我们进入特定问题和陷阱前,首先我想给你下使用SQL Server里的PIVOT能实现什么的一个基本概述. 概述 SQL Server里PIVOT运算符背后的基本思想是在T-SQL查询期间,你可以旋转行为列.运算符本身是SQL Server 2005后引入的,主要用在基于建立在实

浅谈SQL Server 之 PIVOT运算符用法

相信大家在处理数据库编程时,也许会常用到pivot运算符.今天把我近段时间处理的一个简单报表用到pivot运算符与大家分享一下. 比如,针对一个职员基础表tb_Employee(ID,EmpID,EmpName,DptNo,DptDesc,InDate,...),利用pivot分析职工流动率情况.在入职日期不确定的情况下,如何动态处理所要的结果为题. 即,如何实现: SELECT DptNo,Dpt,[2000] AS Y2000,[2001] AS Y2001,[2002] AS Y2002,

监控 SQL Server (2005/2008) 的运行状况--来自微软TetchNet

原文地址:http://technet.microsoft.com/zh-cn/library/bb838723.aspx Microsoft SQL Server 2005 提供了一些工具来监控数据库.方法之一是动态管理视图.动态管理视图 (DMV) 和动态管理函数 (DMF) 返回的服务器状态信息可用于监控服务器实例的运行状况.诊断问题和优化性能. 常规服务器动态管理对象包括: dm_db_*:数据库和数据库对象 dm_exec_*:执行用户代码和关联的连接 dm_os_*:内存.锁定和时间

SQL Server:APPLY表运算符

SQL Server 2005(含)以上版本,新增了APPLY表运算,为我们日常查询带来了极大的方便. 新增的APPLY表运算符把右表表达式应用到左表表达式中的每一行.它不像JOIN那样先计算那个表表达式都可以,APPLY必选先逻辑地计算左表达式.这种计算输入的逻辑顺序允许吧右表达式关联到左表表达式. APPLY有两种形式,一个是OUTER APPLY,一个是CROSS APPLY,区别在于指定OUTER,意味着结果集中将包含使右表表达式为空的左表表达式中的行,而指定CROSS,则相反,结果集中

SQL Server 2005 中的数据类型总结

注:转自土豆网 SQL Server 2005 中的数据类型归纳为下列类别: 精确数字 bigint decimal int numeric smallint money tinyint smallmoney bit 近似数字 float real 日期和时间 datetime smalldatetime 字符串 char text varchar Unicode字符串 nchar ntext nvarchar 二进制字符串 binary image varbinary 其他数据类型 curso

深入理解SQL Server 2005 中的 COLUMNS_UPDATED函数

原文:深入理解SQL Server 2005 中的 COLUMNS_UPDATED函数 概述 COLUMNS_UPDATED函数能够出现在INSERT或UPDATE触发器中AS关键字后的任何位置,用来指示表或视图中有哪些列已被插入或者更新.它通常和IF语句一起使用,从而可以根据不同的结果,促使触发器执行不同的操作.因此在DML触发器中,COLUMNS_UPDATED函数是一个非常重要且有用的函数. 不同于UPDATE函数,COLUMNS_UPDATED函数可以工作在多个列中,它使用字节中的位(B

sql server 2005 怎么看是不是企业版

已经安装了SQL server 2005 怎么确定它是企业版 还是标准版??? 执行sql:SELECT @@VERSION在结果里看,比如我这里是(里面有Enterprise Edition,表示企业版):Microsoft SQL Server 2005 - 9.00.4035.00 (Intel X86) Nov 24 2008 13:01:59 Copyright (c) 1988-2005 Microsoft Corporation Enterprise Edition on Wind

sql server 2005 32位+64位、企业版+标准版、CD+DVD 下载地址大全

企业版DVD SQL Server 2005 Enterprise Edition(支持超大型企业) 32 位DVD: ed2k://|file|cs_sql_2005_ent_x86_dvd.iso|972310528|4CEEF4B959894FD78C8F8416B4BA533E|/ 64 位DVD: ed2k://|file|cs_sql_2005_ent_x64_dvd.iso|1019222016|10FD11133A3E70DAD665BEDC1090AD28|/ 标准版CD SQ

Sql Server 2005的1433端口打开和进行远程连接

参考地址:http://topic.csdn.net/u/20090828/16/e693935a-99b7-4090-a6bc-0123c91183eb.html 1.如何打开sql server 2005 的1433端口配置工具->Sql Server Configuration Manager->MSSQLSERVER的协议看看TCP/IP协议是否启动,如果启动,右键菜单点"属性" ,在分页菜单中选"IP地址",把"IP1"和&