(4) PIVOT 和 UPIVOT 的使用
最近项目中用到了行转列,使用SQL SERVER 提供的PIVOT实现起来非常容易。
官方解释:详见这里
可以使用 PIVOT 和 UNPIVOT 关系运算符将表值表达式更改为另一个表。
PIVOT 通过将表达式某一列中的唯一值转换为输出中的多个列来旋转表值表达式,并在必要时对最终输出中所需的任何其余列值执行聚合。UNPIVOT 与 PIVOT 执行相反的操作,将表值表达式的列转换为列值。
其实PIVOT 就是行转列,UNPIVOT就是列转行。
PIVOT 的完整语法为:
SELECT <非透视的列>,
[第一个透视的列] AS <列名称>,
[第二个透视的列] AS <列名称>,
...
[最后一个透视的列] AS <列名称>,
FROM
(<生成数据的 SELECT 查询>)
AS <源查询的别名>
PIVOT
(
<聚合函数>(<要聚合的列>)
FOR
[<包含要成为列标题的值的列>]
IN ( [第一个透视的列], [第二个透视的列],
... [最后一个透视的列])
) AS <透视表的别名>
<可选的 ORDER BY 子句>;
UNPIVOT的完整语法相对简单一些为:
SELECT <其他列>,<虚拟列别名>,<列值别名>
UNPIVOT(
<列值别名>
FOR <虚拟列别名>
IN(<第一个真实列>,<第二个真实列>....)
) AS <表别名>
我们来看一个简单PIVOT的例子,项目有如下要求:根据用户输入的查询月份,统计所有设备房间此月的告警次数,界面报表要求如下格式:
设备房间 | 告警A次数 | 告警B次数 | 告警C次数 |
XXX | 10 | 1 | 2 |
ZZZ | 1 | 0 | 5 |
例如:数据库中有如下表和数据:
--机房表
create table t_DevRoom
(
RoomId int identity(1,1),
RoomName nvarchar(50),
constraint [Pk_DevRoom_RoomId] primary key clustered(RoomId),
constraint [Uq_DevRoom_RoomName] unique (RoomName)
)
go --告警类型
create table t_AlarmType
(
TypeId int,
TypeName nvarchar(20) not null,
constraint [Pk_AlarmType_TypeId] primary key clustered(TypeId),
constraint [Uq_AlarmType_TypeName] unique (TypeName)
)
go --告警表
create table t_Alarm
(
AlarmId int identity(1,1),
RoomId int not null,
AlarmType int not null,
AlarmDt datetime not null,
constraint [Pk_Alarm_AlarmId] primary key clustered(AlarmId),
constraint [Fk_Alarm_RoomId] foreign key (RoomId) references t_DevRoom(RoomId) on delete cascade,
constraint [Fk_Alarm_AlarmType] foreign key (AlarmType) references t_AlarmType(TypeId) on delete cascade
)
go insert into t_DevRoom values ('机房A')
insert into t_DevRoom values ('机房B')
insert into t_DevRoom values ('机房C') insert into t_AlarmType values (1,'空调告警')
insert into t_AlarmType values (2,'烟雾告警')
insert into t_AlarmType values (3,'设备告警') insert into t_Alarm values(1,1,'2013-01-01')
insert into t_Alarm values(1,1,'2013-01-02')
insert into t_Alarm values(1,2,'2013-01-02')
insert into t_Alarm values(1,3,'2013-01-03')
insert into t_Alarm values(1,3,'2013-01-04') insert into t_Alarm values(2,2,'2013-01-01')
insert into t_Alarm values(2,2,'2013-01-02')
insert into t_Alarm values(2,3,'2013-01-02')
insert into t_Alarm values(2,3,'2013-01-03')
insert into t_Alarm values(2,3,'2013-01-04')
有了上面的临时数据,我们可以查询一下2013年1月份所有机房的告警次数:
select R.RoomId,R.RoomName,count(A.AlarmType) as nums,T.TypeName from t_DevRoom as R
left join t_Alarm as A on R.RoomId=A.RoomId
left join t_AlarmType AS T on A.AlarmType=T.TypeId
WHERE datepart(year,A.AlarmDt)=2013 AND datepart(month,A.AlarmDt)=1 or A.AlarmDt is null
group by R.RoomId,R.RoomName,T.TypeName
order by RoomId
结果如下:
我们来把这个结果集PIVOT一下,以符合我们的界面要求,我们根据语法格式进行这样修改:
select RoomId,RoomName,
alarm_kt=isnull([空调告警],0),
alarm_yw=isnull([烟雾告警],0),
alarm_dv=isnull([设备告警],0)
from
(
select R.RoomId,R.RoomName,T.TypeName,count(A.AlarmType) as nums from t_DevRoom as R
left join t_Alarm as A on R.RoomId=A.RoomId
left join t_AlarmType AS T on A.AlarmType=T.TypeId
WHERE datepart(year,A.AlarmDt)=2013 AND datepart(month,A.AlarmDt)=1 or A.AlarmDt is null
group by R.RoomId,R.RoomName,T.TypeName
) as temp
pivot
(
min(nums) for TypeName IN([空调告警],[烟雾告警],[设备告警])
) as temp2
order by RoomId
查询结果如下:
至于 UNPIVOT 与PIVOT正好相反,也来看个例子,此例子来自于网上:
create table t_score
(
姓名 varchar(10),
语文 int,
数学 int,
物理 int
)
go insert into t_score values('张三',74,83,93)
insert into t_score values('李四',74,84,94) select * from t_score
select 姓名,课程,分数
from t_score
unpivot
(
分数 for 课程 in([语文],[数学],[物理])
) as t
go
执行结果如下:
(4) PIVOT 和 UPIVOT 的使用的更多相关文章
- SQl 行转列,列转行 (PIVOT,UPIVOT)
1.列转行 表t_pivot 转后效果 方法 1 (常用方法 case when) SELECT buydate, SUM(CASE WHEN type = '生活' THEN typec ...
- PIVOT 和 UPIVOT 的使用(行转列)
PIVOT 通过将表达式某一列中的唯一值转换为输出中的多个列来旋转表值表达式,并在必要时对最终输出中所需的任何其余列值执行聚合.UNPIVOT 与 PIVOT 执行相反的操作,将表值表达式的列转换为列 ...
- T-Sql中的pivot和unpivot
写在前面 今天休息,抽空了解下pivot和unpivot,记得老师讲行转列的时候,貌似提到过,不过他说的最多的就是“这个你们私下可以自己学,很简单的...”,简单你咋不讲呢,不吐槽他了,还是好好整理下 ...
- Pivot 和 Unpivot
在TSQL中,使用Pivot和Unpivot运算符将一个关系表转换成另外一个关系表,两个命令实现的操作是“相反”的,但是,pivot之后,不能通过unpivot将数据还原.这两个运算符的操作数比较复杂 ...
- SQL Server中行列转换 Pivot UnPivot
SQL Server中行列转换 Pivot UnPivot PIVOT用于将列值旋转为列名(即行转列),在SQL Server 2000可以用聚合函数配合CASE语句实现 PIVOT的一般语法是:PI ...
- Open xml 操作Excel 透视表(Pivot table)-- 实现Excel多语言报表
我的一个ERP项目中,客户希望使用Excel Pivot table 做分析报表. ERP 从数据库中读出数据,导出到Excel中的数据源表(统一命名为Data),刷新Pivot table! 客户还 ...
- SQL(横表和纵表)行列转换,PIVOT与UNPIVOT的区别和使用方法举例,合并列的例子
使用过SQL Server 2000的人都知道,要想实现行列转换,必须综合利用聚合函数和动态SQL,具体实现起来需要一定的技巧,而在SQL Server 2005中,使用新引进的关键字PIVOT/UN ...
- T-SQL Recipes之Dynamic PIVOT and UNPIVOT
PIVOT PIVOT在行转列的时候经常用到,最便捷的方式就是通过示例来理解它的作用. 示例1 Query to Return Select Product Data from AdventureWo ...
- sql的行转列(PIVOT)与列转行(UNPIVOT)
在做数据统计的时候,行转列,列转行是经常碰到的问题.case when方式太麻烦了,而且可扩展性不强,可以使用 PIVOT,UNPIVOT比较快速实现行转列,列转行,而且可扩展性强 一.行转列 1.测 ...
随机推荐
- log4j写入数据库
转发自http://www.cnblogs.com/adolfmc/p/3432720.html Log4j 配置数据库连接池(将日志信息保存到数据库) org.apache.log4j.jdbc.J ...
- Core Audio(一)
Core Audio APIs core audio apis是vista之后引入的,不使用与之前的windows版本:core audio apis提供访问endpoint devices,比如耳机 ...
- 原创 Datareader 导出为csv文件方法
DataReader 是游标只读数据, 如果是大数据导出,用Datatable 将耗费巨大内存资源.因为Datatable 其实就是内存中的一个数据表 代码如下 /// <summary> ...
- Objective-C 关联
在项目开发中,经常会使用到关联,就是将两个实例对象绑定,使得其中一个实例对象成为另一个实例对象的一部分.关联特性在mac os 10.6 及ios 3.1以上才可以使用. 关联的使用是基于关键字来实现 ...
- mac下配置openCV
预备工作: 1.下载Homebrew 在Terminal中输入: ruby -e "$(curl -fsSkL raw.github.com/mxcl/homebrew/go)" ...
- How to Install JAVA 8 (JDK/JRE 8u111) on Debian 8 & 7 via PPA
Oracle JAVA 8 Stable release has been released on Mar,18 2014 and available to download and install. ...
- [.NET领域驱动设计实战系列]专题十一:.NET 领域驱动设计实战系列总结
一.引用 其实在去年本人已经看过很多关于领域驱动设计的书籍了,包括Microsoft .NET企业级应用框架设计.领域驱动设计C# 2008实现.领域驱动设计:软件核心复杂性应对之道.实现领域驱动设计 ...
- 【腾讯Bugly干货分享】揭秘:微信是如何用libco支撑8亿用户的
本文来自于腾讯bugly开发者社区,未经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/58203cfcd149ba305c5ccf85 作者:Leiffy 导语 lib ...
- nginx(4、缓存)
nginx提供内置的缓存功能,对静态文件,如html\css\js等能够缓存在本地,即nginx服务器的某个目录下. 其配置主要是两部分: 1.在http下配置一个缓存路径: proxy_cache_ ...
- UWP应用开发系列视频教程简介 - Built for Windows 10
万分感谢Fdyo同学给我们带来的有中文字幕的系列教程! http://zhuanlan.zhihu.com/MSFaith/20364660 下面是这系列video教程中的一个截图作为示例,有代码,有 ...