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.查看我的数 ...
随机推荐
- Windows7安装 .net framework 4.0
1.首先下载安装包.net framework 4.0点击下载即可 2.安装,双击下载好的安装包
- ORACLE LINUX 6.3 + ORACLE 11.2.0.3 RAC + VBOX安装文档
ORACLE LINUX 6.3 + ORACLE 11.2.0.3 RAC + VBOX安装文档 2015-10-21 12:51 525人阅读 评论(0) 收藏 举报 分类: Oracle RA ...
- hibernate id 策略
@Id@GeneratedValue(generator = "paymentableGenerator")@GenericGenerator(name = "payme ...
- Django模板与Vue.js冲突问题
参考: https://my.oschina.net/soarwilldo/blog/755984 方法1:修改vue.js的默认的绑定符号 Vue.config.delimiters = [&quo ...
- Java中的堆栈区别
在函数中定义的一些基本类型的变量和对象的引用变量都在函数的栈内存中分配. 当在一段代码块定义一个变量时,Java就在栈中为这个变量分配内存空间,当超过变量的作用域后,Java会自动释放掉为该变量所分配 ...
- PostgreSQL 允许远程访问设置方法
安装PostgreSQL数据库之后,默认是只接受本地访问连接.如果想在其他主机上访问PostgreSQL数据库服务器,就需要进行相应的配置. 配置远程连接PostgreSQL数据库的步骤很简单,只需 ...
- QT插件使用
1基本插件制作流程 1) 定义接口.接口定义为抽象基类,如IPluginInterface,实现高度封装.定义的头文件在最后需要通过Q_DECLARE_INTERFACE来唯一标识该接口,即通过一个全 ...
- 从SQLite获取数据完成一个产品信息展示
在ios实际开发当中,我们常常用到Core Data做为数据储存首选.但在处理一些大量复杂的数据值且数据之间相互关联的时候,这就不得不使用关系型数据库来实现.例如一个导航程序,自身应该包含大量的地图自 ...
- zookeeper3.3.6 伪分布式安装
下载地址(http://zookeeper.apache.org/releases.html#download) 一:下载zookeeper的安装包,解压,进入到zk的目录文件,进入conf目录 ...
- Swift - 键盘弹起,遮挡输入框
extension LoginViewController:UITextFieldDelegate { func textFieldShouldReturn(textField: UITextFiel ...