Pivot 和 Unpivot
在TSQL中,使用Pivot和Unpivot运算符将一个关系表转换成另外一个关系表,两个命令实现的操作是“相反”的,但是,pivot之后,不能通过unpivot将数据还原。这两个运算符的操作数比较复杂,记录一下自己的总结,以后用到时,作为参考。
一,Pivot用法
Pivot旋转的作用,是将关系表(table_source)中的列(pivot_column)的值,转换成另一个关系表(pivot_table)的列名:
table_source
pivot
(
aggregation_function(aggregated_column)
for pivot_column in ([pivot_column_value_list])
) as pivot_table_alias
透视操作的处理流程是:
- 对pivot_column和 aggregated_column的其余column进行分组,即,group by other_columns;
- 当pivot_column值等于某一个指定值,计算aggregated_column的聚合值;
在使用透视命令时,需要注意:
- pivot将table_source旋转成透视表(pivot_table)之后,不能再被引用
- pivot_column的列值,必须使用中括号([])界定符
- 必须显式命名pivot_table的别名
1,创建示例数据
use tempdb
go drop table if exists dbo.usr
go create table dbo.usr
(
name varchar(10),
score int,
class varchar(8)
)
go insert into dbo.usr
values('a',20,'math'),('b',21,'math'),('c',22,'phy'),('d',23,'phy')
,('a',22,'phy'),('b',23,'phy'),('c',24,'math'),('d',25,'math')
go

2,对name进行分组,对score进行聚合,将class列的值转换为列名
select p.name,p.math,p.phy
from dbo.usr u
pivot
(
sum(score)
for class in([math],[phy])
) as p

3,pivot的等价写法:使用case when语句实现
pivot命令的执行流程很简单,使用caseh when子句实现pivot的功能
select u.name,
sum(case when u.class='math' then u.score else null end) as math,
sum(case when u.class='phy' then u.score else null end) as phy
from dbo.usr u
group by u.name
使用group by子句对name列分组,使用 case when 语句将pivot_column的列值作为列名返回,并对aggregated_column计算聚合值。
4,动态Pivot写法
静态pivot写法的弊端是:如果pivot_column的列值发生变化,静态pivot不能对新增的列值进行透视,变通方法是使用动态sql,拼接列值
Script1,使用case-when子句实现
declare @sql nvarchar(max)
declare @columnlist nvarchar(max) set @columnlist=N'' ;with cte as
(
select distinct class
from dbo.usr
)
select @columnlist+='sum(case when u.class='''+cast(class as varchar(10))+N''' then u.score else null end) as ['+cast(class as varchar(10))+N'],'
from cte select @columnlist=SUBSTRING(@columnlist,1,len(@columnlist)-1) select @sql=
N'select u.name,'
+@columnlist
+N'from dbo.usr u
group by u.name' exec(@sql)
Script2,使用pivot子句实现
declare @sql nvarchar(max)
declare @classlist nvarchar(max) set @classlist=N'' ;with cte as
(
select distinct class
from dbo.usr
)
select @classlist+=N'['+cast(class as varchar(11))+N'],'
from cte select @classlist=SUBSTRING(@classlist,1,len(@classlist)-1) select @sql=N'select p.name,'+@classlist+
N' from dbo.usr u
PIVOT
(
sum(score)
for class in('+@classlist+N')
) as p' exec (@sql)
二,Unpivot用法
unpivot是将列名转换为列值,列名做为列值,因此,会新增两个column:一个column用于存储列名,一个column用于存储列值
table_soucr
unpivot
(
newcolumn_store_unpivotcolumn_name for
newcolumn_store_unpivotcolumn_value in (unpivotcolumn_name_list)
)
逆透视(unpivot)的处理流程是:
- unpivotcolumn_name_list是逆透视列的列表,其列值是相兼容的,能够存储在一个column中
- 保持其他列(除unpivotcolumn_name_list之外的所有列)的列值不变
- 依次将unpivotcolumn的列名存储到newcolumn_store_unpivotcolumn_name字段中,将unpivotcolumn的列值存储到newcolumn_store_unpivotcolumn_value字段中
1,创建示例数据
CREATE TABLE dbo.Venders
(
VendorID int,
Emp1 int,
Emp2 int,
Emp3 int,
Emp4 int,
Emp5 int
);
GO INSERT INTO dbo.Venders VALUES (1,4,3,5,4,4);
INSERT INTO dbo.Venders VALUES (2,4,1,5,5,5);
INSERT INTO dbo.Venders VALUES (3,4,3,5,4,4);
INSERT INTO dbo.Venders VALUES (4,4,2,5,5,4);
INSERT INTO dbo.Venders VALUES (5,5,1,5,5,5);
GO

2,unpivot用法示例
将Emp1, Emp2, Emp3, Emp4, Emp5的列名和列值存储到字段:Employee和Orders中
SELECT VendorID, Employee, Orders
FROM dbo.Venders as p
UNPIVOT
(Orders FOR Employee IN
(Emp1, Emp2, Emp3, Emp4, Emp5)
)AS unpvt;
GO

3,unpivot可以使用union all来实现
select VendorID, 'Emp1' as Employee, Emp1 as Orders
from dbo.Venders
union all
select VendorID, 'Emp2' as Employee, Emp2 as Orders
from dbo.Venders
union all
select VendorID, 'Emp3' as Employee, Emp3 as Orders
from dbo.Venders
union all
select VendorID, 'Emp4' as Employee, Emp4 as Orders
from dbo.Venders
union all
select VendorID, 'Emp5' as Employee, Emp5 as Orders
from dbo.Venders
4,动态unpivot的实现,使用动态sql语句
聪明如你,很容易实现,代码就不贴了....
三,性能讨论
pivot和unpivot的性能不是很好,不要用来处理海量的数据
参考文档:
Pivot 和 Unpivot的更多相关文章
- SQL(横表和纵表)行列转换,PIVOT与UNPIVOT的区别和使用方法举例,合并列的例子
使用过SQL Server 2000的人都知道,要想实现行列转换,必须综合利用聚合函数和动态SQL,具体实现起来需要一定的技巧,而在SQL Server 2005中,使用新引进的关键字PIVOT/UN ...
- [转]使用 PIVOT 和 UNPIVOT
可以使用 PIVOT 和 UNPIVOT 关系运算符将表值表达式更改为另一个表.PIVOT 通过将表达式某一列中的唯一值转换为输出中的多个列来旋转表值表达式,并在必要时对最终输出中所需的任何其余列值执 ...
- 使用 PIVOT 和 UNPIVOT
http://msdn.microsoft.com/zh-cn/library/ms177410%28v=SQL.90%29.aspx 可以使用 PIVOT 和 UNPIVOT 关系运算符将表值表达式 ...
- 通过sql做数据透视表,数据库表行列转换(pivot和Unpivot用法)(一)
在mssql中大家都知道可以使用pivot来统计数据,实现像excel的透视表功能 一.MSsqlserver中我们通常的用法 1.Sqlserver数据库测试 ---创建测试表 Create tab ...
- 使用 PIVOT 和 UNPIVOT 行转列 列转行 报表统计 函数
官方文档:http://technet.microsoft.com/zh-cn/library/ms177410(v=SQL.105).aspx 可以使用 PIVOT 和 UNPIVOT 关系运算符将 ...
- T-Sql中的pivot和unpivot
写在前面 今天休息,抽空了解下pivot和unpivot,记得老师讲行转列的时候,貌似提到过,不过他说的最多的就是“这个你们私下可以自己学,很简单的...”,简单你咋不讲呢,不吐槽他了,还是好好整理下 ...
- sql pivot、unpivot和partition by用法
原文:sql pivot.unpivot和partition by用法 演示脚本 from sys.sysobjects where name = 'Student' AND type = 'U') ...
- pivot 与 unpivot 函数是SQL05新提供的2个函数
pivot 与 unpivot 函数是SQL05新提供的2个函数 ----------------------------------------------------------------- ...
- PIVOT和UNPIVOT使用详解
一.使用PIVOT实现数据表的列转行 建表语句: DROP TABLE STUDENT; CREATE TABLE STUDENT ( 学生编号 BYTE) NULL , 姓名 BYTE) NULL ...
随机推荐
- Python编码记录
字节流和字符串 当使用Python定义一个字符串时,实际会存储一个字节串: "abc"--[97][98][99] python2.x默认会把所有的字符串当做ASCII码来对待,但 ...
- 【原】AFNetworking源码阅读(二)
[原]AFNetworking源码阅读(二) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 上一篇中我们在iOS Example代码中提到了AFHTTPSessionMa ...
- node中子进程同步输出
管道 通过"child_process"模块fork出来的子进程都是返回一个ChildProcess对象实例,ChildProcess类比较特殊无法手动创建该对象实例,只能使用fo ...
- 就这么漂来漂去---一个毕业三个月的java程序员的裸辞风波
注:这并不是一篇技术文章,而是记录了我这几个月经历的入职,裸辞,找工作的心路历程,简单介绍一个博主的情况,我是16年毕业生,校招进了一家北京的公司,java开发,和很多年轻人一样,干了一段时间,我发现 ...
- 安装angular-cli
最近在学习angular2,并尝试用这个框架来做公司的一个新项目. 终于要开始开发了,等了1个多月. 因为第一次用这个新框架做项目,不太熟悉,就找了angular-cli这个脚手架来搭建项目. 安装了 ...
- isEmpty和isNull()区别
isEmpty和isNull()区别一个NULL字符串一定是一个空串,一个空串未必是一个NULL字符串例如:QString().isNull(): //结果为trueQString().isEm ...
- Canvas讲解
1.Canvas是什么? 简单地说canvas是画布,可以进行画任何的线.图形.填充等一系列的操作,而且操作的画图就是js, 提供简单的二维矢量绘图. 2.步骤: <canvas id=&quo ...
- arcgis api for js入门开发系列七图层控制(含源代码)
上一篇实现了demo的地图分屏对比模块,本篇新增图层控制模块,截图如下(源代码见文章底部): 图层控制模块实现的思路如下: 1.在地图配置文件map.config.js里面配置图层目录树节点信息,作为 ...
- 使用四元数解决万向节锁(Gimbal Lock)问题
问题 使用四元数可以解决万向节锁的问题,但是我在实际使用中出现问题:我设计了一个程序,显示一个三维物体,用户可以输入绕zyx三个轴进行旋转的指令,物体进行相应的转动. 由于用户输入的是绕三个轴旋转的角 ...
- 从is(":checked")说起
*此文所用jQuery版本应大于1.6.1 如何判断一个单选(复选)框是否选中. 对于刚接触jQuery的人,第一反应必然是. <input id="checkbox1" ...