PIVOT 和 UPIVOT 的使用(行转列)
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

执行结果如下:

PIVOT 和 UPIVOT 的使用(行转列)的更多相关文章
- PIVOT内置函数实现行转列
PIVOT用于将列值旋转为列名(即行转列),PIVOT的一般语法是:PIVOT(聚合函数(列) FOR 列 in (…) )AS P 完整语法: table_source PIVOT( 聚合函数(va ...
- PIVOT运算符使用(动态行转列)
PIVOT运算符用于在列和行之间对数据进行旋转或透视转换,同时执行聚合运算 官方的语法如下: PIVOT( 聚合函数(value_column) FOR pivot_column IN(<col ...
- T-SQL 实现行转列
问题: 我正在寻找一种有效的方式将行转换为SQL服务器中的列 例如,通过下表如何构建出预期结果表. Id Value ColumnName 1 John FirstName 2 2 ...
- SQl 行转列,列转行 (PIVOT,UPIVOT)
1.列转行 表t_pivot 转后效果 方法 1 (常用方法 case when) SELECT buydate, SUM(CASE WHEN type = '生活' THEN typec ...
- sql的行转列(PIVOT)与列转行(UNPIVOT)
在做数据统计的时候,行转列,列转行是经常碰到的问题.case when方式太麻烦了,而且可扩展性不强,可以使用 PIVOT,UNPIVOT比较快速实现行转列,列转行,而且可扩展性强 一.行转列 1.测 ...
- SQL Server中使用PIVOT行转列
使用PIVOT行转列 1.建表及插入数据 USE [AdventureDB] GO /****** Object: Table [dbo].[Score] Script Date: 11/25/201 ...
- SQL Server 2008 R2——PIVOT 行转列 以及聚合函数的选择
==================================声明================================== 本文原创,转载在正文中显要的注明作者和出处,并保证文章的完 ...
- 微软BI 之SSIS 系列 - 在 SQL 和 SSIS 中实现行转列的 PIVOT 透视操作
开篇介绍 记得笔者在 2006年左右刚开始学习 SQL Server 2000 的时候,遇到一个面试题就是行转列,列转行的操作,当时写了很长时间的 SQL 语句最终还是以失败而告终.后来即使能写出来, ...
- SQL2008 R2 SP3中使用pivot实现行转列
同事遇到一个问题,怎么实现行转列,参考了别人的示例,我是这样解决的. 创建数据源: create table #temp ( objectid int, sitename ), cities ), p ...
随机推荐
- 【MFC】画线
1.DrawTestDlg.h afx_msg void OnLButtonDown(UINT nFlags, CPoint point); afx_msg void OnLButtonUp(UINT ...
- POCO库中文编程参考指南(5)Poco::Net::SocketAddress
1 枚举 最大地址长度,这个与Poco::Net::IPAddress中的定义可以类比,不过这里指的是`struct sockaddr_in6 enum { MAX_ADDRESS_LENGTH = ...
- 处理下最近的file_id小写问题
update t_resource_info set FILE_ID = UPPER(FILE_ID);update t_resource_my_info set FILE_ID = UPPER(FI ...
- 【原创】SQL Server Job邮件详细配置
1 简介 SQL Server 代理具有发送电子邮件的功能.您可以配置 SQL Server 代理邮件,使其在出现下列情况时向预定义的操作员发送电子邮件: 警报触发时.可以配置警报,以针对所发生的特定 ...
- [BZOJ1295][SCOI2009]最长距离 最短路+枚举
1295: [SCOI2009]最长距离 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1683 Solved: 912[Submit][Statu ...
- linux 系统的负载与CPU、内存、硬盘、用户数监控脚本[marked]
转载文章 原始出处 在没有nagios监控的情况下,只要服务器能上互联网,就可通过发邮件的方式来提醒管理员系统资源的使用情况. 一.编写linux系统告警邮件脚本 # vim /scripts/sy ...
- 树链剖分【p1505】[国家集训队]旅游
Description Ray 乐忠于旅游,这次他来到了T 城.T 城是一个水上城市,一共有 N 个景点,有些景点之间会用一座桥连接.为了方便游客到达每个景点但又为了节约成本,T 城的任意两个景点之间 ...
- 洛谷——P1067 多项式输出
P1067 多项式输出 题目描述 一元 n 次多项式可用如下的表达式表示: 其中,aixi称为 i 次项,ai 称为 i 次项的系数.给出一个一元多项式各项的次数和系数,请按照如下规定的格式要求输出该 ...
- PMBOK及PMP考试精要
PROJECT MANAGEMENT KNOWLEDGE AREAS项目管理知识体系 2 PROJECT LIFE CYCLE / PROJECT MANAGEMENT PROCESS GROUPS项 ...
- luogu P1361 小M的作物
题目链接 luogu P1361 小M的作物 题解 源汇点为A,B 向种子连边,容量为价值,每个种子能与A或B联通,考虑最小割 用建边的总流量减去最小割就是答案 相同利益的时候新建节点,由额外利益构成 ...