T-SQL Recipes之Dynamic PIVOT and UNPIVOT
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的更多相关文章
- 使用 PIVOT 和 UNPIVOT 行转列 列转行 报表统计 函数
官方文档:http://technet.microsoft.com/zh-cn/library/ms177410(v=SQL.105).aspx 可以使用 PIVOT 和 UNPIVOT 关系运算符将 ...
- SQL(横表和纵表)行列转换,PIVOT与UNPIVOT的区别和使用方法举例,合并列的例子
使用过SQL Server 2000的人都知道,要想实现行列转换,必须综合利用聚合函数和动态SQL,具体实现起来需要一定的技巧,而在SQL Server 2005中,使用新引进的关键字PIVOT/UN ...
- 通过sql做数据透视表,数据库表行列转换(pivot和Unpivot用法)(一)
在mssql中大家都知道可以使用pivot来统计数据,实现像excel的透视表功能 一.MSsqlserver中我们通常的用法 1.Sqlserver数据库测试 ---创建测试表 Create tab ...
- Dynamic Pivot table wizard SQL Server
原文 http://www.gyurcit.hu/pivot.html Dynamic Pivot table wizard This stored procedure generate dynami ...
- sql pivot、unpivot和partition by用法
原文:sql pivot.unpivot和partition by用法 演示脚本 from sys.sysobjects where name = 'Student' AND type = 'U') ...
- sql 行转列 PIVOT 列转行 UNPIVOT
原文:sql 行转列 PIVOT 列转行 UNPIVOT 一: 现有表一(t_table1),想转为表二(t_table2)的格式. 表一: 年 公司 收入 2013 公司1 12 2013 公司2 ...
- SQL行转列(PIVOT)与列转行(UNPIVOT)简明方法
原文地址:https://www.cnblogs.com/linJie1930906722/p/6036714.html 在做数据统计的时候,行转列,列转行是经常碰到的问题.case when方式太麻 ...
- sql行列转换PIVOT与unPIVOT
基本语法 select * from Mould pivot ( count(ID)for ProductTypeCode in ( [FC], [RCU], [RCD] )) as PVT; wit ...
- SQL Server 行列相互转换命令:PIVOT和UNPIVOT使用详解
一.使用PIVOT和UNPIVOT命令的SQL Server版本要求 1.数据库的最低版本要求为SQL Server 2005 或更高. 2.必须将数据库的兼容级别设置为90 或更高. 3.查看我的数 ...
随机推荐
- Ajax商品分类三级联动实现
思路分析: 效果:当页面加载时,利用ajax异步向后台请求数据,加载一级商品类别,当选择一级商品时加载二级商品,选择二级商品加载三级商品. 实现: 1.当拿到数据后加载pid为0的商品,并动态创建op ...
- //给定N个整数序列{A1,A2,A3...An},求函数f(i,j)=(k=i~j)Ak的求和
//给定N个整数序列{A1,A2,A3...An},求函数f(i,j)=(k=i~j)Ak的求和 # include<stdio.h> void main() { ,sum1; ]={,- ...
- [转载]PV操作简单理解
原文链接:http://blog.csdn.net/liushuijinger/article/details/7586656 进程通常分为就绪.运行和阻塞三个工作状态.三种状态在某些条件下可以转 ...
- 常用js代码集
<img src="{:url('publics/verify')}" onclick="this.src='{:url('publics/verify')}'&q ...
- JavaFx导出文件
导出文件格式可选 protected void handExportDateAction(ActionEvent event) { // ShowDialog.showConfirmDialog(FX ...
- 【JavaScript】JS 中 原始字符串 和 HTML 字符转换
参考资料:http://www.sjyhome.com/javascript/js-html-escape.html JS转换HTML转义符 SJY • 发表于:2013年10月05日 17:04 • ...
- 【Kubernetes】K8S网络方案--最近在看的
K8S网络-最近在看的 Create a Minikube cluster - Kubernetes Kubernetes Documentation - Kubernetes Kubernetes ...
- cat命令
[cat] 合并文件和打印到标准输出 命令格式: cat [OPTION]... [FILE]... 命令功能: 拼接文件或者做标准输入输出 命令格式: cat [OPTION].. ...
- java并行计算Fork和Join的使用
Java在JDK7之后加入了并行计算的框架Fork/Join,可以解决我们系统中大数据计算的性能问题.Fork/Join采用的是分治法,Fork是将一个大任务拆分成若干个子任务,子任务分别去计算,而J ...
- win8 app GridView点击子项布局变更
要触发点击必须设置IsItemClickEnabled="True" 要变更布局代码如下: private void gridView_ItemClick_1(object sen ...