SQL server 2005 UNPIVOT运算符的使用

      UNPIVOT运算符相对于PIVOT运算符,它执行与PIVOT相反的操作,即将列转换到行。需要注意的是UNPIVOT运算符并不完全是PIVOT的逆向操作。因为执行PIVOT将会执行一次聚合,从而将多个可能的行合并为输出中的单个行。而 UNPIVOT 无法重现原始表值表达式的结果,因为行已经被合并了。另外,UNPIVOT 的输入中的空值不会显示在输出中,而在执行 PIVOT 操作之前,输入中可能有原始的空值。

      关于PIVOT运算符的使用,请参考:SQL server 2005 PIVOT运算符的使用

一、UNPIVOT的语法

SELECT
        [DataType]
      ,   [DataValue]
      ,   [UnpivotedCol1]
      ,   [UnpivotedCol2]
      ,   [UnpivotedCol3]
     FROM table
     UNPIVOT
      (
        [DataValue] FOR [DataType]
        IN ([UnpivotedCol1],[UnpivotedCol1],[UnpivotedCol3],etc..)
      )
      AS Alias

--需要注意的是,对于每一个UNPIVOT列值,必须使用中括号括起来。
二、UNPIVOT的使用例子

     我们使用了SQL server 2005 PIVOT运算符的使用文章中的例子。如下所示,从NorthWind数据库生成数据源及PIVOT表。

1.静态UNPIVOT的用法

    USE tempdb
    GO
    SELECT YEAR(OrderDate) AS [Year]  --从NorthWind提取演示示例所需数据
           ,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')
        AND od.Quantity > 20;

    SELECT * FROM dbo.Orders;
    /*以下列出部分结果集,年的数据省略
    Year        CustomerID Quantity
    ----------- ---------- --------
    1996        BONAP      40
    1996        BONAP      50
    1996        BONAP      24
    1996        ANTON      24
    1996        BOTTM      30
    1997        BOTTM      49
    1997        BOTTM      25
    1997        BOTTM      40
    1997        BOTTM      50
    1997        BOTTM      50
    1997        BOTTM      30
    */

    --1->.生成PIVOT数据
    SELECT CustomerID
    	,[1996],[1997],[1998]
    INTO #pivot_result
    FROM dbo.Orders
    PIVOT (
    	   SUM(Quantity)
    	   FOR [Year] IN ([1996],[1997],[1998])
       )x

    /* Result:
    CustomerID 1996        1997        1998
    ---------- ----------- ----------- -----------
    ANTON      24          205         NULL
    BONAP      114         356         122
    BOTTM      30          389         292
    */

    --2->.生成UNPIVOT数据,实现列到行的转换
    SELECT CustomerID
           ,Year
           ,Quantity
    FROM #pivot_result
    UNPIVOT
      (
        Quantity FOR Year IN ([1996],[1997],[1998])
      )  x    

    /* Result:
    CustomerID Year        Quantity
    ---------- ----------- -----------
    ANTON      1996        24
    ANTON      1997        205
    BONAP      1996        114
    BONAP      1997        356
    BONAP      1998        122
    BOTTM      1996        30
    BOTTM      1997        389
    BOTTM      1998        292
    */

    --从上面的结果中我们看出CustomerID为ANTON用户在年,Quantity的值为NULL,即没有订单,使用UNPIOVT后忽略掉了NULL值。
    --注意UNPIVOT后并没有回到PIVOT之前的数据,因为实现PIVOT后数据已经被汇总。

    --3->.在UNPIVOT后的结果中重现NULL值
    SELECT CustomerID
           ,Year
           ,CASE WHEN Quantity = 0 THEN NULL ELSE Quantity END AS Quantity --还原为NULL的值
    FROM (
    	SELECT CustomerID,Year,Quantity
    		FROM (
    		SELECT CustomerID,
    		  ISNULL([1996],0) AS [1996] --对年份列增加了一个ISNULL的判断
    		  ,ISNULL([1997],0) AS [1997]
    		  ,ISNULL([1998],0) AS [1998]
    		  FROM #pivot_result) AS  pivot_result
    		UNPIVOT
    		  (
    			Quantity FOR Year IN ([1996],[1997],[1998])
    		  )  x
    	)y

    /*
    CustomerID Year    Quantity
    ---------- ------- -----------
    ANTON      1996     24
    ANTON      1997     205
    ANTON      1998     NULL  --NULL值重现
    BONAP      1996     114
    BONAP      1997     356
    BONAP      1998     122
    BOTTM      1996     30
    BOTTM      1997     389
    BOTTM      1998     292
    */

2.动态UNPIVOT的用法

 USE tempd;
    GO
    DECLARE @UnpivotColHeader NVARCHAR(MAX)
            ,@UnpivotTableSQL NVARCHAR(MAX);
    SELECT @UnpivotColHeader =  --将列标题转换为行值
        STUFF(
          (SELECT N','+ QUOTENAME(x) AS [text()]
    	   FROM (
    	          SELECT COLUMN_NAME AS x
    	    	  FROM INFORMATION_SCHEMA.COLUMNS
    		      WHERE TABLE_SCHEMA = N'dbo'
    			    AND TABLE_NAME = N'pivot_result'
    			    AND COLUMN_NAME NOT IN(N'CustomerID')
    			) AS x
           ORDER BY x
           FOR XML PATH('')),
           1,1,N'');
    SET @UnpivotTableSQL =
    	'SELECT CustomerID
           ,Year
           ,CASE WHEN Quantity = 0 THEN NULL ELSE Quantity END AS Quantity
    	FROM (
    		SELECT CustomerID,Year,Quantity
    			FROM (
    			SELECT CustomerID,
    			  ISNULL([1996],0) AS [1996]
    			  ,ISNULL([1997],0) AS [1997]
    			  ,ISNULL([1998],0) AS [1998]
    			  FROM pivot_result) AS  pivot_result
    			UNPIVOT
    			  (
    				Quantity FOR Year IN (' + @UnpivotColHeader + ')
    			  )  x
    	)y' + N';';

    EXEC sp_executesql @UnpivotTableSQL;

    --结果同上

三、总结

1.UNPIVOT操作符的第一个输入是保存被旋转属性值(Quantity)的目标列名称。

2.FOR关键字,指定保存被旋转列名称(Year)的目标列名称。

3.在IN子句的圆括号,指定要旋转的源列名称([1996],[1997],[1998])。

 

PIVOT运算符的使用,请参阅:http://blog.csdn.net/robinson_0612/archive/2010/03/16/5385117.aspx

时间: 2024-03-18 10:36:44

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

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-p

在SQL Server 2005中实现表的行列转换

PIVOT和UNPIVOT关系运算符是SQL Server 2005提供的新增功能,因此,对升级到SQL Server 2005的数据库使用PIVOT和UNPIVOT时,数据库的兼容级别必须设置为90(可以使用sp_dbcmptlevel存储过程设置兼容级别). 在查询的FROM子句中使用PIVOT和UNPIVOT,可以对一个输入表值表达式执行某种操作,以获得另一种形式的表.PIVOT运算符将输入表的行旋转为列,并能同时对行执行聚合运算.而UNPIVOT运算符则执行与PIVOT运算符相反的操作,

使用 SQL Server 2005中的 CLR 集成

本文描述了数据库应用程序开发人员和架构师如何利用 SQL Server 2005 中的 CLR 集成功能.本文对基于 CLR 的编程方式与 SQL Server 中支持的现有编程模型(如 TransacT-SQL 和扩展存储过程)进行了比较,并且强调了各自相对的优缺点.还提供了一组选择合适的编程替代方法的高级指导,以及一些示例和代码示例. 一.简介 Microsoft 通过宿主 Microsoft .NET Framework 2.0 公共语言运行库 (CLR),SQL Server 2005显

SQL Server 2005中的T-SQL增强

server 丰富的数据类型 Richer Data Types 1.varchar(max).nvarchar(max)和varbinary(max)数据类型最多可以保存2GB的数据,可以取代text.ntext或image数据类型.CREATE TABLE myTable(    id INT,    content VARCHAR(MAX)) 2.XML数据类型XML数据类型允许用户在SQL Server数据库中保存XML片段或文档. 错误处理 Error Handling 1.新的异常处

Microsoft SQL Server 2005 中的 XML 支持(1)

本文探讨 SQL Server 2005 中内置的 XML 支持.描述了这种支持如何与 .NET 框架 V2.0 和本机代码(例如 OLEDB 和 SQLXML)均支持的客户端编程相集成. 一.简介 可扩展标记语言 (XML) 作为一种与平台无关的数据表示形式已被广泛采用.它对于在松散耦合且完全不同的系统,以及各种企业到企业 (B2B) 应用和工作流范畴内交换信息是很有用的.数据交换已成为 XML 技术的主要驱动力之一.. XML 在企业应用程序中的使用正日益广泛,它主要用于对半结构化和非结构化

SQL Server 2005 中的商务智能和数据仓库(1)

本文概述了 SQL Server 2005 Beta 2 中"商务智能"平台的增强功能.本文并非实施指南,而是为读者提供了关于"商务智能"平台增强功能的信息. 一.简介 Microsoft SQL Server 2005 是一个完整的商务智能 (BI) 平台,其中为用户提供了可用于构建典型和创新的分析应用程序所需的各种特性.工具和功能.本文简要介绍了您在构建分析应用程序时将要用到的一些工具,并着重介绍了一些新增功能,这些新增功能使复杂 BI 系统的构建和管理比以往更

图文解析SQL Server 2005与2000兼容性

看来,你已经决定要从SQL Server 2000升级到SQL 2005了. 你可能已经在你的桌面电脑和测试环境中安装了一个SQL Server 2000的实例并想要进行适当的升级.或者你可能只是想安装一个新的SQL Server 2005实例.本文将主要关注安装新实例时可能遇到的问题,同时本文也将对两个版本之间交互的选项(比如连接服务器.多服务器管理.日志传递)进行分析. 在SQL 2000主机上安装SQL Server 2005 如果你想在你的SQL Server 2000主机上安装SQL

在 SQL Server 2005 中使用表值函数来实现空间数据库

server|函数|数据|数据库 Gyorgy Fekete 和 Alex Szalay约翰霍普金丝大学 Jim GrayMicrosoft(联系作者) 适用于Microsoft SQL Server 2005 摘要:本文说明了如何使用 C# 和表值函数将空间搜索函数("邻近点的点"和"多边形内的点")添加到 Microsoft SQL Server 2005.使用此库可以在不编写任何特殊代码的情况下向应用程序中添加空间搜索.此库实现了来自约翰霍普金丝大学的公共域

SQL Server 2005常见问题浅析

问题1:使用.net2005自带的SQL-Express连接不上. 解决方法: 1.网络防火墙阻止数据库连接: 2.默认SQL-Express没有启动Sa账户->下载一个management studio express界面工具管理SQL-Express 3.无线网络会出现根据机器名找不到SQL服务器的情况,直接用IP连接 4.服务端通过开始菜单打开->配置工具->SQL Server外围应用配置器->服务和连接的外围应用配置器->远程连接->右边选择"本地连