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使用时必须列的数量和类型相对应。
SQL server 2005 PIVOT运算符的使用的更多相关文章
- SQL Server里PIVOT运算符的”红颜祸水“
在今天的文章里我想讨论下SQL Server里一个特别的T-SQL语言结构——自SQL Server 2005引入的PIVOT运算符.我经常引用这个与语言结构是SQL Server里最危险的一个——很 ...
- 监控 SQL Server (2005/2008) 的运行状况
Microsoft SQL Server 2005 提供了一些工具来监控数据库.方法之一是动态管理视图.动态管理视图 (DMV) 和动态管理函数 (DMF) 返回的服务器状态信息可用于监控服务器实例的 ...
- SQL Server:APPLY表运算符
SQL Server 2005(含)以上版本,新增了APPLY表运算,为我们日常查询带来了极大的方便. 新增的APPLY表运算符把右表表达式应用到左表表达式中的每一行.它不像JOIN那样先计算那个表表 ...
- SQL Server数据库PIVOT函数的使用详解(一)
http://database.51cto.com/art/201108/285250.htm SQL Server数据库中,PIVOT在帮助中这样描述滴:可以使用 PIVOT 和UNPIVOT 关系 ...
- 转载--SQL Server 2005的XQuery介绍
原文地址: http://bbs.51cto.com/thread-458009-1-1.html 引用: 摘要 本文介绍了SQL Server 2005能够支持的XQuery的各方面特性如FLW ...
- SQL Server 2005入门到精通(案例详解)
SQL Server 2005基础应用 一.数据库的基本操作 --创建数据库 create database new_db2 on primary ( name='new.mdf', filena ...
- 深入理解SQL Server 2005 中的 COLUMNS_UPDATED函数
原文:深入理解SQL Server 2005 中的 COLUMNS_UPDATED函数 概述 COLUMNS_UPDATED函数能够出现在INSERT或UPDATE触发器中AS关键字后的任何位置,用来 ...
- 回首经典的SQL Server 2005
原创文章转载请注明出处:@协思, http://zeeman.cnblogs.com SQL Server是我使用时间最长的数据库,算起来已经有10年了.上世纪90年代,微软在软件开发的所有领域高歌猛 ...
- windows10下sql server 2005 无法运行或sql server服务无法启动的完美解决方案
问题:升级windows10后,sql server 2005 无法运行或sql server服务&sql server agent无法启动,如下图,怎么办? 一般情况下,我们第一反应就是sq ...
随机推荐
- 最经常使用的两种C++序列化方案的使用心得(protobuf和boost serialization)
导读 1. 什么是序列化? 2. 为什么要序列化?优点在哪里? 3. C++对象序列化的四种方法 4. 最经常使用的两种序列化方案使用心得 正文 1. 什么是序列化? 程序猿在编写应用程序的时候往往须 ...
- WPF案例 (四) 模拟Windows7桌面任务栏
原文:WPF案例 (四) 模拟Windows7桌面任务栏 这个程序模彷了Windows7的桌面任务栏,当在桌面上双击某个快捷方式时,将打开一个新的子界面,并且在任务栏里创建一个链接到此界面的任务栏图标 ...
- Visual Studio Installer打包后生成的安装文件每次执行都需要重新安装C++ 2010运行库(x86)的解决方案
原文:Visual Studio Installer打包后生成的安装文件每次执行都需要重新安装C++ 2010运行库(x86)的解决方案 如果你是用Visual Studio自带的打包项目打包了一个I ...
- OPEN-E安装中注意的问题
安装OPEN-E的时候,OPEN-E需要单独安装到存储硬盘外的硬盘上,否则是没有办法使用安装了OPEN-E的硬盘上的空间的. OPEN-E免费许可证的容量问题 安装OPEN-E后申请的试用key只能试 ...
- 聊聊高并发(三十八)解析java.util.concurrent各个组件(十四) 理解Executor接口的设计
JUC包中除了一系列的同步类之外,就是Executor运行框架相关的类.对于一个运行框架来说,能够分为两部分 1. 任务的提交 2. 任务的运行. 这是一个生产者消费者模式,提交任务的操作是生产者,运 ...
- 【DRP】删除递归树的操作
正如图呈现的树结构.本文从任意节点删除树形结构.提供解决方案 图中,不包括其他结点的是叶子结点.包括其他结点的是父结点,即不是叶子结点. 一 本文的知识点: (1)递归调用: 由于待删除的结点的层次是 ...
- ubuntu终端方向键不能用(主机名不显示)问题的解决
sudo gedit /etc/passwd 在/etc/passwd中改动该用户相应的shell:/bin/sh改为/bin/bash就可以解决该问题
- maven仓库总结,maven私服搭建
配置pom.xml依赖包时在这里找包的描述: http://search.maven.org/#browse 以java为根目录. mvn archtype:generate -DgroupId=zt ...
- HttpURLConnection请求数据流的写入(write)和读取(read)
URLConnection类给应用 程序 和web资源之间架设起了通信的桥梁,这些web资源通常是通过url来标记的,本文将讲述如何使用HttpURLConnection来访问web页面(发送数据流) ...
- Xamarin.Android中使用android:onClick="xxx"属性
原文:Xamarin.Android中使用android:onClick="xxx"属性 在原生Android开发中,为一个View增加点击事件,有三种方式: 1.使用匿名对象 ( ...