PIVOT

PIVOT在行转列的时候经常用到,最便捷的方式就是通过示例来理解它的作用。

示例1 Query to Return Select Product Data from AdventureWorks

SELECT  PRODUCT.Name AS product_name ,
PRODUCT.Color AS product_color ,
PRODUCT_INVENTORY.LocationID ,
PRODUCT.ReorderPoint ,
PRODUCT_INVENTORY.Quantity AS product_quantity
FROM Production.Product PRODUCT
LEFT JOIN Production.ProductInventory PRODUCT_INVENTORY ON PRODUCT.ProductID = PRODUCT_INVENTORY.ProductID;

结果:

如果我们想要product_coor 在列里面显示每个产品的数量呢?这时候PIVOT就出场了

示例2:Common Use of PIVOT to Report on Products by Color

WITH    PRODUCT_DATA
AS ( SELECT PRODUCT.Name AS product_name ,
PRODUCT.Color AS product_color ,
PRODUCT.ReorderPoint ,
PRODUCT_INVENTORY.Quantity AS product_quantity
FROM Production.Product PRODUCT
LEFT JOIN Production.ProductInventory PRODUCT_INVENTORY ON PRODUCT.ProductID = PRODUCT_INVENTORY.ProductID
)
SELECT *
FROM PRODUCT_DATA PIVOT
( SUM(product_quantity) FOR product_color IN ( [Black], [Blue], [Grey],
[Multi], [Red], [Silver],
[Silver/Black], [White],
[Yellow] ) ) PIVOT_DATA;

结果:

从SQL中可以看出PIVOT有两个步骤

  • An aggregate function, which will aggregate if multiple values exist. In the initial
    SELECT statement that returns product data, there were many duplicate rows. This
    example uses SUM whenever this occurs, which will add up product quantities if there
    are multiple rows with the same product name.

  • A value list for all values that will be changed from row data into column headers. In
    this case, the list is of colors from Product.Color .

PS:虽然解决了行转列的问题,但这个时候,我们应该知道color里面到底有多少条唯一的数据,如果在我们不知的情况下,如何解决呢?这个时候动态SQL就来了。

示例3:Common Use of PIVOT to Report on Products by Color

USE AdventureWorks2014;
GO DECLARE @sql_command NVARCHAR(MAX);
DECLARE @sql_colors NVARCHAR(1000); SET @sql_command = '
WITH PRODUCT_DATA
AS ( SELECT PRODUCT.Name AS product_name ,
PRODUCT.Color AS product_color ,
PRODUCT.ReorderPoint ,
PRODUCT_INVENTORY.Quantity AS product_quantity
FROM Production.Product PRODUCT
LEFT JOIN Production.ProductInventory PRODUCT_INVENTORY ON PRODUCT.ProductID = PRODUCT_INVENTORY.ProductID
)
SELECT *
FROM PRODUCT_DATA PIVOT
( SUM(product_quantity) FOR product_color IN (';
WITH colorlist
AS ( SELECT DISTINCT
Product.Color AS color_name
FROM Production.Product
WHERE Product.Color IS NOT NULL
)
SELECT @sql_colors = ISNULL(@sql_colors, N'') + N','
+ QUOTENAME(color_name)
FROM colorlist; SET @sql_colors = STUFF(@sql_colors, 1, 1, ''); SET @sql_command = @sql_command + @sql_colors + N' )) PIVOT_DATA'; PRINT @sql_command;
EXEC sp_executesql @sql_command;

首先看一下打印出来的SQL:

WITH    PRODUCT_DATA
AS ( SELECT PRODUCT.Name AS product_name ,
PRODUCT.Color AS product_color ,
PRODUCT.ReorderPoint ,
PRODUCT_INVENTORY.Quantity AS product_quantity
FROM Production.Product PRODUCT
LEFT JOIN Production.ProductInventory PRODUCT_INVENTORY ON PRODUCT.ProductID = PRODUCT_INVENTORY.ProductID
)
SELECT *
FROM PRODUCT_DATA PIVOT
( SUM(product_quantity) FOR product_color IN ( [Black], [Blue], [Grey],
[Multi], [Red], [Silver],
[Silver/Black], [White],
[Yellow] ) ) PIVOT_DATA

结果:

从示例1到示例3,我们从中了解到如何把复杂的SQL慢慢分解出来,最后在组合在一起。

UNPIVOT

顾名思义,就是PIVOT的反向操作:列转行。我们还是从简单的示例到复杂的示例看慢慢了解。

PS:为了方便,就直接用上面的数据来做列转行。

示例1:Using UNPIVOT to Revert Column Headers into Row Data

WITH    PRODUCT_DATA
AS ( SELECT PRODUCT.Name AS product_name ,
PRODUCT.Color AS product_color ,
PRODUCT.ReorderPoint ,
PRODUCT_INVENTORY.Quantity AS product_quantity
FROM Production.Product PRODUCT
LEFT JOIN Production.ProductInventory PRODUCT_INVENTORY ON PRODUCT.ProductID = PRODUCT_INVENTORY.ProductID
),
PRODUCTS_BY_COLOR
AS ( SELECT *
FROM PRODUCT_DATA PIVOT
( SUM(product_quantity) FOR product_color IN ( [Black], [Blue], [Grey],
[Multi], [Red], [Silver],
[Silver/Black], [White],
[Yellow] ) ) PIVOT_DATA
)
SELECT *
FROM PRODUCTS_BY_COLOR UNPIVOT
( product_quantity FOR Color IN ( [Black], [Blue], [Grey], [Multi], [Red],
[Silver], [Silver/Black], [White], [Yellow] ) ) AS UNPIVOT_DATA;

从SQL中可以看出,UNPIVOT同样有两个步骤,这里就不详说了,可以查看MSND了解更多。

PS:我们必须指定列转行里面的字段,如果数据库增加了一个color,那我们必须要更改这段SQL,除非我们用动态SQL来实现。

示例2: A Dynamic UNPIVOT Using Original Row Data to Supply Color Names

USE AdventureWorks2014;
GO DECLARE @sql_command NVARCHAR(MAX);
DECLARE @sql_pivotcommand NVARCHAR(MAX);
DECLARE @sql_unpivotcommand NVARCHAR(MAX); DECLARE @sql_colors NVARCHAR(1000); SET @sql_pivotcommand = '
WITH PRODUCT_DATA
AS ( SELECT PRODUCT.Name AS product_name ,
PRODUCT.Color AS product_color ,
PRODUCT.ReorderPoint ,
PRODUCT_INVENTORY.Quantity AS product_quantity
FROM Production.Product PRODUCT
LEFT JOIN Production.ProductInventory PRODUCT_INVENTORY ON PRODUCT.ProductID = PRODUCT_INVENTORY.ProductID
),
PRODUCTS_BY_COLOR
AS ( SELECT *
FROM PRODUCT_DATA PIVOT ( SUM(product_quantity) FOR product_color IN (';
WITH colorlist
AS ( SELECT DISTINCT
Product.Color AS color_name
FROM Production.Product
WHERE Product.Color IS NOT NULL
)
SELECT @sql_colors = ISNULL(@sql_colors, N'') + N','
+ QUOTENAME(color_name)
FROM colorlist; SET @sql_colors = STUFF(@sql_colors, 1, 1, ''); SET @sql_pivotcommand = @sql_pivotcommand + @sql_colors + N' )) PIVOT_DATA)'; SET @sql_unpivotcommand = ' SELECT *
FROM PRODUCTS_BY_COLOR UNPIVOT ( product_quantity FOR Color IN (' + @sql_colors + ') ) AS UNPIVOT_DATA'; SET @sql_command = @sql_pivotcommand + @sql_unpivotcommand; PRINT @sql_command;
EXEC sp_executesql @sql_command;

打印出来的SQL:

WITH    PRODUCT_DATA
AS ( SELECT PRODUCT.Name AS product_name ,
PRODUCT.Color AS product_color ,
PRODUCT.ReorderPoint ,
PRODUCT_INVENTORY.Quantity AS product_quantity
FROM Production.Product PRODUCT
LEFT JOIN Production.ProductInventory PRODUCT_INVENTORY ON PRODUCT.ProductID = PRODUCT_INVENTORY.ProductID
),
PRODUCTS_BY_COLOR
AS ( SELECT *
FROM PRODUCT_DATA PIVOT
( SUM(product_quantity) FOR product_color IN ( [Black], [Blue], [Grey],
[Multi], [Red], [Silver],
[Silver/Black], [White],
[Yellow] ) ) PIVOT_DATA
)
SELECT *
FROM PRODUCTS_BY_COLOR UNPIVOT ( product_quantity FOR Color IN (
[Black], [Blue], [Grey],
[Multi], [Red], [Silver],
[Silver/Black], [White],
[Yellow] ) ) AS UNPIVOT_DATA

结果:

咦?这结果不是PIVOT示例1的么?怎么绕了一大圈又回到原地了?突然感觉神农百草结尾时说,这草有毒!

T-SQL Recipes之Dynamic PIVOT and UNPIVOT的更多相关文章

  1. 使用 PIVOT 和 UNPIVOT 行转列 列转行 报表统计 函数

    官方文档:http://technet.microsoft.com/zh-cn/library/ms177410(v=SQL.105).aspx 可以使用 PIVOT 和 UNPIVOT 关系运算符将 ...

  2. SQL(横表和纵表)行列转换,PIVOT与UNPIVOT的区别和使用方法举例,合并列的例子

    使用过SQL Server 2000的人都知道,要想实现行列转换,必须综合利用聚合函数和动态SQL,具体实现起来需要一定的技巧,而在SQL Server 2005中,使用新引进的关键字PIVOT/UN ...

  3. 通过sql做数据透视表,数据库表行列转换(pivot和Unpivot用法)(一)

    在mssql中大家都知道可以使用pivot来统计数据,实现像excel的透视表功能 一.MSsqlserver中我们通常的用法 1.Sqlserver数据库测试 ---创建测试表 Create tab ...

  4. Dynamic Pivot table wizard SQL Server

    原文 http://www.gyurcit.hu/pivot.html Dynamic Pivot table wizard This stored procedure generate dynami ...

  5. sql pivot、unpivot和partition by用法

    原文:sql pivot.unpivot和partition by用法 演示脚本 from sys.sysobjects where name = 'Student' AND type = 'U') ...

  6. sql 行转列 PIVOT 列转行 UNPIVOT

    原文:sql 行转列 PIVOT 列转行 UNPIVOT 一: 现有表一(t_table1),想转为表二(t_table2)的格式. 表一: 年 公司 收入 2013 公司1 12 2013 公司2 ...

  7. SQL行转列(PIVOT)与列转行(UNPIVOT)简明方法

    原文地址:https://www.cnblogs.com/linJie1930906722/p/6036714.html 在做数据统计的时候,行转列,列转行是经常碰到的问题.case when方式太麻 ...

  8. sql行列转换PIVOT与unPIVOT

    基本语法 select * from Mould pivot ( count(ID)for ProductTypeCode in ( [FC], [RCU], [RCD] )) as PVT; wit ...

  9. SQL Server 行列相互转换命令:PIVOT和UNPIVOT使用详解

    一.使用PIVOT和UNPIVOT命令的SQL Server版本要求 1.数据库的最低版本要求为SQL Server 2005 或更高. 2.必须将数据库的兼容级别设置为90 或更高. 3.查看我的数 ...

随机推荐

  1. 【Android自学日记】【转】Android Fragment 真正的完全解析(下)

    上篇博客中已经介绍了Fragment产生原因,以及一些基本的用法和各种API,如果你还不了解,请看:Android Fragment 真正的完全解析(上). 本篇将介绍上篇博客提到的:如何管理Frag ...

  2. 转:aliyun阿里云Maven仓库地址——加速你的maven构建

    maven仓库用过的人都知道,国内有多么的悲催.还好有比较好用的镜像可以使用,尽快记录下来.速度提升100倍. http://maven.aliyun.com/nexus/#view-reposito ...

  3. JAVA 各种数值类型最大值和最小值 Int, short, char, long, float,&nbs

    转载地址:http://blog.sina.com.cn/s/blog_5eab3d430101fdv6.html 代码片段: fmax = Float.MAX_VALUE; fmin = Float ...

  4. AliSQL的编译使用

    1.下载源码 git clone https://github.com/alibaba/AliSQL.git Linux下编译 2.编译 编译前需要安装好gcc cmake bison等.(如果缺少其 ...

  5. redis lua

    需求是在缓存最近一周内用户所有消息列表,考虑用Redis 存储:为每个存储一个独立Sorted Set,value 为消息体,Score 为MessageId,用以实现增量消息同步. 问题就来了:So ...

  6. angular 自定义指令 directive transclude 理解

    项目中断断续续的用了下angular,也没狠下心 认真的学习.angular 特别是自定义指令这块 空白. transclude 定义是否将当前元素的内容转移到模板中.看解释有点抽象. 看解释有点抽象 ...

  7. 设计模式--桥接模式Bridge(结构型)

    一.概述 在软件系统中,某些类型由于自身的逻辑,它具有两个或者多个维度的变化,如何应对这种"多维度的变化",就可以利用桥接模式. 引例: 设想如果要绘制矩形.圆形.椭圆.正方形,我 ...

  8. Python~字典

    if not isinstance(x, (int, float)): raise TypeError('bad operand type')   range() raw_input(‘birth’) ...

  9. Mac OS X 上安装 ASP.NET 5

    在Mac OS X Yosemite 10.10.3 中搭建第一个 ASP.NET 5 Web 项目 终于有时间在 Mac 上安装一下 ASP.NET 5,网上有许多教程,但是多数的时间比较早了,版本 ...

  10. Java POI 解析word文档

    实现步骤: 1.poi实现word转html 2.模型化解析html 3.html转Map数组 Map数组(数组的操作处理不做说明) 1.导jar包. 2.代码实现 package com.web.o ...