SQL server 2005 UNPIVOT运算符的使用

本文涉及的产品
云数据库 RDS SQL Server,独享型 2核4GB
简介:       UNPIVOT运算符相对于PIVOT运算符,它执行与PIVOT相反的操作,即将列转换到行。需要注意的是UNPIVOT运算符并不完全是PIVOT的逆向操作。
+关注继续查看

      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

相关实践学习
使用交互方式创建数据表
本次实验主要介绍如何在RDS-SQLServer数据库中使用交互方式创建数据表。
SQL Server on Linux入门教程
SQL Server数据库一直只提供Windows下的版本。2016年微软宣布推出可运行在Linux系统下的SQL Server数据库,该版本目前还是早期预览版本。本课程主要介绍SQLServer On Linux的基本知识。 相关的阿里云产品:云数据库RDS SQL Server版 RDS SQL Server不仅拥有高可用架构和任意时间点的数据恢复功能,强力支撑各种企业应用,同时也包含了微软的License费用,减少额外支出。 了解产品详情: https://www.aliyun.com/product/rds/sqlserver
目录
相关文章
|
1天前
|
SQL 关系型数据库 MySQL
SQL Server重置自增的值为0
SQL Server重置自增的值为0
13 0
|
1天前
|
SQL 关系型数据库 Apache
Microsoft SQL Server 迁移到 PostgreSQL 利器:Babelfish
Babelfish for PostgreSQL 加速了将 Microsoft SQL Server 应用程序迁移到 PostgreSQL 的旅程。Babelfish for PostgreSQL 是一个开源项目,可在 Apache 2.0 和 PostgreSQL 许可下使用。它使 PostgreSQL 能够理解来自 Microsoft SQL Server 编写的应用程序的查询。Babelfish 了解 SQL Server 有线协议和 Microsoft SQL Server 查询语言 T-SQL,此您不必切换数据库驱动程序或重新编写所有应用程序查询。
167 0
|
1天前
|
SQL 数据库
SQL Server 数据查询
SQL Server 数据查询
58 0
|
1天前
|
SQL 数据库 数据安全/隐私保护
SQL Server 数据操控,视图和索引
SQL Server 数据操控,视图和索引
67 0
|
1天前
|
SQL 存储 Go
SQL Server 创建与管理数据库实验报告
SQL Server 创建与管理数据库实验报告
17 1
|
1天前
|
SQL Go 数据库
SQL Server创建及修改表实验报告(下)
SQL Server创建及修改表实验报告(上)
17 0
|
1天前
|
SQL 数据库 Python
SQL Server创建及修改表实验报告(上)
SQL Server创建及修改表实验报告
28 1
|
1天前
|
SQL 数据库
SQL Server 创建和管理数据表
SQL Server 创建和管理数据表
25 1
|
1天前
|
SQL 数据库
SQL Server 连接查询和子查询
SQL Server 连接查询和子查询
54 0
|
1天前
|
SQL 数据库
SQL Server 单表数据查询
SQL Server 单表数据查询
69 1
推荐文章
更多