最近项目中用到了行转列,使用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 的使用的更多相关文章

  1. SQl 行转列,列转行 (PIVOT,UPIVOT)

    1.列转行 表t_pivot 转后效果   方法 1 (常用方法 case when) SELECT     buydate, SUM(CASE WHEN type = '生活' THEN typec ...

  2. PIVOT 和 UPIVOT 的使用(行转列)

    PIVOT 通过将表达式某一列中的唯一值转换为输出中的多个列来旋转表值表达式,并在必要时对最终输出中所需的任何其余列值执行聚合.UNPIVOT 与 PIVOT 执行相反的操作,将表值表达式的列转换为列 ...

  3. T-Sql中的pivot和unpivot

    写在前面 今天休息,抽空了解下pivot和unpivot,记得老师讲行转列的时候,貌似提到过,不过他说的最多的就是“这个你们私下可以自己学,很简单的...”,简单你咋不讲呢,不吐槽他了,还是好好整理下 ...

  4. Pivot 和 Unpivot

    在TSQL中,使用Pivot和Unpivot运算符将一个关系表转换成另外一个关系表,两个命令实现的操作是“相反”的,但是,pivot之后,不能通过unpivot将数据还原.这两个运算符的操作数比较复杂 ...

  5. SQL Server中行列转换 Pivot UnPivot

    SQL Server中行列转换 Pivot UnPivot PIVOT用于将列值旋转为列名(即行转列),在SQL Server 2000可以用聚合函数配合CASE语句实现 PIVOT的一般语法是:PI ...

  6. Open xml 操作Excel 透视表(Pivot table)-- 实现Excel多语言报表

    我的一个ERP项目中,客户希望使用Excel Pivot table 做分析报表. ERP 从数据库中读出数据,导出到Excel中的数据源表(统一命名为Data),刷新Pivot table! 客户还 ...

  7. SQL(横表和纵表)行列转换,PIVOT与UNPIVOT的区别和使用方法举例,合并列的例子

    使用过SQL Server 2000的人都知道,要想实现行列转换,必须综合利用聚合函数和动态SQL,具体实现起来需要一定的技巧,而在SQL Server 2005中,使用新引进的关键字PIVOT/UN ...

  8. T-SQL Recipes之Dynamic PIVOT and UNPIVOT

    PIVOT PIVOT在行转列的时候经常用到,最便捷的方式就是通过示例来理解它的作用. 示例1 Query to Return Select Product Data from AdventureWo ...

  9. sql的行转列(PIVOT)与列转行(UNPIVOT)

    在做数据统计的时候,行转列,列转行是经常碰到的问题.case when方式太麻烦了,而且可扩展性不强,可以使用 PIVOT,UNPIVOT比较快速实现行转列,列转行,而且可扩展性强 一.行转列 1.测 ...

随机推荐

  1. shell学习

    set -x 进入调试模式,会把每一个命令实际执行的命令打印出来,也就是会把一些参数扩展后的样子打印出来. set +x 退出调试模式自定义变量:x=7,y=8echo `expr $x + $y` ...

  2. Hyper-V初涉:Hyper-V虚拟机常规操作

    a. 连接到虚拟机与开机 在Hyper-V管理器中双击待启动的虚拟机或在待启动的虚拟机上右键选择"启动"即可完成连接虚拟机的操作. 若此时虚拟机正在运行则直接进入虚拟机界面,若虚拟 ...

  3. 第8章 NAND FLASH控制器

    8.1 NAND Flash介绍和NAND Flash控制器使用 NAND Flash在嵌入式系统中的地位与PC上的硬盘类似 NAND Flash在掉电后仍可保存 8.1.1 Flash介绍 有NOR ...

  4. python 装饰器初步学习

    第一步 简单函数 ''' 简单的函数:调用两次''' def myfunc(): print ('myfunc() called.') myfunc() myfunc() 第二步 装饰器为调用函数提供 ...

  5. C#操作内存读写方法的主要实现代码

    C#操作内存读写方法是什么呢?让我们来看看具体的实例实现: using System.Runtime.InteropServices; using System.Text; publicclass F ...

  6. ORACLE10g创建表空间,角色与授权

    创建基础表空间,创建用户,授权. -- CREATE TABLESPACE CREATE TABLESPACE TS_JK_LAB_BASIC DATAFILE 'D:\TOOLS\ORACLE\PR ...

  7. [Asp.net 开发系列之SignalR篇]专题五:SignalR支持的平台

    SignalR支持多种服务器和客户端配置.此外,每种传输方式都有自身的要求限制:如果某种传输方式不被系统支持,SignalR能够优雅地将故障转移到其他类型的传输方式.关于SignalR所支持的传输方式 ...

  8. 冲刺阶段 day13

    ---恢复内容开始--- 项目进展 今天星期三,我们将专业管理部分又继续做了完善,之前漏掉的几项功也一一补全,没能实现的数据库部分也已经进行了完善,并且对已经完成的部分进行了检测,数据库的部分还有待进 ...

  9. Oracle存在修改,不存在插入记录

    接触编程以来,在数据存储方面一直用的MS SQL.Oracle这名字对我来说是如此的熟悉,但是对其内容却很陌生,最近公司的一个项目用起了Oracle,所以也开始高调的用起了Oracle.在没有接触Or ...

  10. Linq动态条件

    很多情况下,我们开发程序,需要动态拼接SQL查询语句; 比如  select top 1 * from User where age= 18  and  name = 'renruiquan' 其中红 ...