(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.测 ...
随机推荐
- HDU 1051 Wooden Sticks
题意: 有 n 根木棒,长度和质量都已经知道,需要一个机器一根一根地处理这些木棒. 该机器在加工过程中需要一定的准备时间,是用于清洗机器,调整工具和模板的. 机器需要的准备时间如下: 1.第一根需要1 ...
- loadRunner 负载机连接错误分析
错误信息: Error: Process "lr_bridge.exe" was not created on remote host "192.168.86.17&qu ...
- .NET环境下导出Excel表格的两种方式和导入两种类型的Excel表格
一.导出Excel表格的两种方式,其中两种方式指的是导出XML数据类型的Excel(即保存的时候可以只需要修改扩展名为.xls)和真正的Excel这两种. using System; using Sy ...
- DOM技术实现竞赛题页面
DOM技术实现竞赛题页面 这一段时间学习了DOM操作和JS开发,我就自己开发一个竞赛题的页面. 一.业务需求 1.目标:做一个一百道选择题的页面 2.功能: 显示题目和选项. 下一题上一题的按钮,到第 ...
- sql 动态语句
如果动态语句有表变量 例子如下: declare @mS varchar(10) declare @mE varchar(10) declare @mSQL nvarchar(500) --SQL语句 ...
- SQL入门经典(四)之创建和修改数据表
本章主要讲如何使用脚本创建数据库:如何使用脚本创建表:如何删除对象和修改对象. CREATE 语句:CREATE <object type> <onject name> 创建数 ...
- ListView 加载更多列表 Load More mono forandroid 项目笔记
今天项目经理找我说Listview加载更多的时候会出现一些问题,主要表现在会顿一下.让我我就去找Java的方法看看.自己写出了mono 的加载更多功能.和大家分享一下 先看效果 首先是模型类ListI ...
- 视频教程--ASP.NET MVC 使用 Petapoco 微型ORM框架+NpgSql驱动连接 PostgreSQL数据库
说好的给园子里的朋友们录制与<ASP.NET MVC 使用 Petapoco 微型ORM框架+NpgSql驱动连接 PostgreSQL数据库> 这篇博客相对应的视频,由于一个月一来没有时 ...
- kernel 内核安装
1.kernel 下载 https://cdn.kernel.org/pub/linux/kernel/ 2.解压源码 tar -zxvf linux-*.tar.gz 3.进入目录 cd linux ...
- phpmyadmin Wrong permissions on configuration file, should not be world writable!
巴拉巴拉,实际场景是这样,因为有需要,所以想用django 做个rest服务给其他平台提供服务,发现以前正常的页面都无法运行,奇怪发现有一个页面提示连接不上mysql 难道mysql挂了,打开phpm ...