设为首页 收藏本站
查看: 507|回复: 0

[经验分享] SQL server 2005 PIVOT运算符的使用

[复制链接]

尚未签到

发表于 2016-11-5 05:55:54 | 显示全部楼层 |阅读模式
  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 tempdbGOSELECT YEAR(OrderDate) AS [Year],CustomerID ,od.QuantityINTO dbo.Orders       FROM NorthWind..Orders AS oJOIN NorthWind..[Order Details] AS odON o.OrderID = od.OrderIDWHERE o.CustomerID IN ('BONAP','BOTTM','ANTON')SELECT CustomerID,[1996],[1997],[1998]FROM dbo.OrdersPIVOT (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 TotalFROM dbo.OrdersGROUP BY CustomerID,[Year]ORDER BY CustomerID   /*Result:   CustomerID Year        Total---------- ----------- -----------ANTON      1996        24ANTON      1997        295ANTON      1998        40BONAP      1996        181BONAP      1997        486BONAP      1998        313BOTTM      1996        81BOTTM      1997        454BOTTM      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         40BONAP      181         486         313BOTTM      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,OrderQtyFROM Production.WorkOrder)WorkOrderPIVOT (SUM(OrderQty)FOR [Month] IN ([January],[February],[March],[April],[May],[June],[July],[August],[September],[October],[November],[December]))xORDER 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的默认值为30FROM Sales.SalesTerritoryGROUP BY Name/*--第二种生成透视列的方法,使用了FOR XML PATH方法SELECT @PivotColHeader = STUFF((     SELECT DISTINCT ',[' + cast(Name as varchar) + ']'FROM Sales.SalesTerritoryFOR XML PATH('')),1,1,'')*/DECLARE @PivotTableSQL NVARCHAR(MAX)SET @PivotTableSQL = N'SELECT *FROM (SELECT YEAR(H.OrderDate) [Year],T.Name,H.TotalDueFROM Sales.SalesOrderHeader HLEFT JOIN Sales.SalesTerritory TON H.TerritoryID = T.TerritoryID)AS PivotDataPIVOT(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.SalesTerritoryDECLARE @PivotTableSQL NVARCHAR(MAX)SET @PivotTableSQL = N'SELECT *FROM (SELECT CAST(YEAR(H.OrderDate) AS CHAR(4)) [Year],T.Name,H.TotalDueFROM Sales.SalesOrderHeader HLEFT JOIN Sales.SalesTerritory TON H.TerritoryID = T.TerritoryID)AS PivotDataPIVOT(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.TotalDueFROM Sales.SalesOrderHeader HLEFT JOIN Sales.SalesTerritory TON H.TerritoryID = T.TerritoryID) AS PivotDataPIVOT(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使用时必须列的数量和类型相对应。
  
  

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-295837-1-1.html 上篇帖子: 如何从 ASP 调用 SQL Server 存储过程 下篇帖子: SQL SERVER 2012 使用订阅发布同步数据库(一)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表