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 ...
随机推荐
- JavaScript String对象
本编主要介绍String 字符串对象. 目录 1. 介绍:阐述 String 对象的说明以及定义方式. 2. 实例属性:介绍 String 对象的实例属性: length. 3. 实例方法:介绍 St ...
- OpenSceneGraph in ActiveX by ActiveQt
OpenSceneGraph in ActiveX by ActiveQt eryar@163.com Abstract. Qt’s ActiveX and COM support allows Qt ...
- CoreCRM 开发实录——想用国货不容易
昨天(2016年12月29日)发了开始开发的文章.本来晚上准备在 Coding.NET 上添加几个任务开始搞起了.可是真的开始用的时候才发现:Coding.NET 的任务功能只针对私有的任务开放.我想 ...
- 谈谈一些有趣的CSS题目(七)-- 消失的边界线问题
开本系列,谈谈一些有趣的 CSS 题目,题目类型天马行空,想到什么说什么,不仅为了拓宽一下解决问题的思路,更涉及一些容易忽视的 CSS 细节. 解题不考虑兼容性,题目天马行空,想到什么说什么,如果解题 ...
- iOS逆向工程之Hopper+LLDB调试第三方App
LLDB是Low Level Debugger的简称,在iOS开发的调试中LLDB是经常使用的,LLDB是Xcode内置的动态调试工具.使用LLDB可以动态的调试你的应用程序,如果你不做其他的额外处理 ...
- 将DataTable中的某列转换成数组或者List
string[] arrRate = dtRate.AsEnumerable().Select(d => d.Field<string>("arry")).ToA ...
- 【Java每日一题】20170104
20170103问题解析请点击今日问题下方的"[Java每日一题]20170104"查看(问题解析在公众号首发,公众号ID:weknow619) package Jan2017; ...
- 【夯实PHP基础】PHP数组,字符串,对象等基础面面观
本文地址 分享提纲 1.数组篇 2.字符创篇 3.函数篇 4.面向对象篇 5.其他篇 /*************************** 一.数组篇 Begin***************** ...
- Linux的学习笔记
Linux,1991年,系统安全,良好的可移植性,多用户,多任务,良好的兼容性,良好的用户界面, 主流的是RedHat或者CentOS, CentOS 设置的网关 192.168.2.2 Window ...
- 从贝叶斯到粒子滤波——Round 1
粒子滤波确实是一个挺复杂的东西,从接触粒子滤波到现在半个多月,博主哦勒哇看了N多篇文章,查略了嗨多资料,很多内容都是看了又看,细细斟酌.今日,便在这里验证一下自己的修炼成果,请各位英雄好汉多多指教. ...