SQL Server 使用 Pivot 和 UnPivot 实现行列转换
对于行列转换的数据,通常也就是在做报表的时候用的比较多,之前也零零散散的看了一些,今天就来总结一下。
先创建一个用于演示的临时表:
- create table #temp
- (
- 年份 nvarchar(10) null,
- 月份 nvarchar(10) null,
- 数量 int null
- )
- insert into #temp(年份,月份,数量)
- select '','','' union
- select '','','' union
- select '','','' union
- select '','','' union
- select '','','' union
- select '','','' union
- select '','','' union
- select '','','' union
- select '','',''
- select * from #temp
下面来实现一些需求:
需求一,按年份分组,不同的月份为一列。
- -- 按年份分组,不同的月份为一列
- select t.年份,
- sum(case t.月份 when '' then t.数量 end) '1月份',
- sum(case t.月份 when '' then t.数量 end) '2月份',
- sum(case t.月份 when '' then t.数量 end) '3月份'
- from #temp t
- group by t.年份
另外两种方法:
- -- 使用左外连接查询
- select t.年份,t1.数量 '1月份',t2.数量 '2月份',t3.数量 '3月份' from #temp t
- left join (select 年份,数量 from #temp where 月份='') t1 on t.年份=t1.年份
- left join (select 年份,数量 from #temp where 月份='') t2 on t.年份=t2.年份
- left join (select 年份,数量 from #temp where 月份='') t3 on t.年份=t3.年份
- group by t.年份,t1.数量,t2.数量,t3.数量
- -- 使用自连接查询
- select t.年份,t1.数量 '1月份',t2.数量 '2月份',t3.数量 '3月份'
- from #temp t,
- (select 年份,数量 from #temp where 月份='') t1,
- (select 年份,数量 from #temp where 月份='') t2,
- (select 年份,数量 from #temp where 月份='') t3
- where t.年份=t1.年份 and t.年份=t2.年份 and t.年份=t3.年份
- group by t.年份,t1.数量,t2.数量,t3.数量
返回的结果都是一样的,可以看见这几种方法都是可以实现的(当然,可能还有更多的方法待发掘),不过比起第一种方法,后面这两种方法也太低效了吧,比如一年有12个月份的数据,有个七八年的,那得写多少个子查询、表连接的,而且第一种方法也不是我们想要的。那么就需要用到 Pivot 这种方法了。
Pivot 语法:
- table_source -- 表名称,即数据源
- PIVOT(
- 聚合函数(value_column) -- value_column 要转换为 列值 的列名
- FOR pivot_column -- pivot_column 指定要转换的列
- IN(<column_list>) -- column_list 自定义的目标列名
- )
因为这里列名不允许指定为数字,真是无语。。。我重建了一个数据结构一模一样的表。
- create table #temp
- (
- Name nvarchar(10) null,
- Course nvarchar(10) null,
- Score int null
- )
- insert into #temp(Name,Course,Score)
- select '小李','语文','' union
- select '小李','数学','' union
- select '小李','英语','' union
- select '小明','语文','' union
- select '小明','数学','' union
- select '小明','英语','' union
- select '小红','语文','' union
- select '小红','数学','' union
- select '小红','英语',''
- select * from #temp
- go
- select Name 姓名,
- max(case Course when '语文' then Score end) 语文,
- max(case Course when '数学' then Score end) 数学,
- max(case Course when '英语' then Score end) 英语,
- sum(Score) 课程总分,
- cast(avg(Score) as decimal(18,2)) 课程平均分
- from #temp
- group by Name
使用 Pivot 进行 行转列:
- select a.Name 姓名,a.语文,a.数学,a.英语
- from #temp
- pivot
- (
- max(Score) -- 指定作为转换的列的值 的列名
- for Course -- 指定要转换的列的列名
- in(语文,数学,英语) -- 自定义的目标列名,即要转换列的不同的值作为列
- )a
- select a.Name 姓名,a.语文,a.数学,a.英语,b.SumScore 课程总分,b.AvgScore 课程平均分
- from #temp
- pivot
- (
- max(Score) -- 指定作为转换的列的值 的列名
- for Course -- 指定要转换的列的列名
- in(语文,数学,英语) -- 自定义的目标列名,即要转换列的不同的值作为列
- )a,
- (
- select t.Name,sum(t.Score) SumScore,cast(avg(t.Score) as decimal(18,2)) AvgScore
- from #temp t
- group by t.Name
- )b
- where a.Name=b.Name
UnPivot 语法:
- table_source -- 表名称,即数据源
- UNPIVOT(
- value_column -- value_column 要转换为 行值 的列名
- FOR pivot_column -- pivot_column 指定要转换为指定的列
- IN(<column_list>) -- column_list 目标列名
- )
- create table #temp
- (
- Name nvarchar(10) null,
- Chinese int null,
- Math int null,
- English int null
- )
- insert into #temp(Name,Chinese,Math,English)
- select '小李','','','' union
- select '小明','','','' union
- select '小红','','',''
- select * from #temp
- go
- select t.Name 姓名,t.Course 课程,t.Score 分数 from
- (select t.Name,Course='Chinese',Score=Chinese from #temp t
- union all
- select t.Name,Course='Math',Score=Math from #temp t
- union all
- select t.Name,Course='English',Score=English from #temp t) t
- order by t.Name,t.Course
- select t.Name 姓名,t.Course 课程,t.Score 分数 from
- (select t.Name,'Chinese' Course,Chinese Score from #temp t
- union all
- select t.Name,'Math',Math from #temp t
- union all
- select t.Name,'English',English from #temp t) t
- order by t.Name,t.Course
使用 UnPivot 进行 列转行:
- select t.Name 姓名,t.Course 课程,t.Score 分数
- from #temp
- unpivot
- (
- Score for Course
- in(Chinese,Math,English)
- )t
SQL Server 使用 Pivot 和 UnPivot 实现行列转换的更多相关文章
- SQL server 2005 PIVOT运算符的使用
原文:SQL server 2005 PIVOT运算符的使用 PIVOT,UNPIVOT运算符是SQL server 2005支持的新功能之一,主要用来实现行到列的转换.本文主要介绍PIVOT运算符的 ...
- SQL Server数据库PIVOT函数的使用详解(一)
http://database.51cto.com/art/201108/285250.htm SQL Server数据库中,PIVOT在帮助中这样描述滴:可以使用 PIVOT 和UNPIVOT 关系 ...
- SQL Server里PIVOT运算符的”红颜祸水“
在今天的文章里我想讨论下SQL Server里一个特别的T-SQL语言结构——自SQL Server 2005引入的PIVOT运算符.我经常引用这个与语言结构是SQL Server里最危险的一个——很 ...
- SQL Server将查询出数据进行列转行操作
在日常的SQL Server数据查询时经常会遇到需要将数据列转换成行的操作,现将自己学习的列转行SQL语句举例如下: --首先查询语句 SELCT * FROM YXBAK..TBYJKSTEMP ...
- SQL Server数据库PIVOT函数的使用详解(二)
动态的行转列 原理就是 把需要转成列的行拼出来 DECLARE @fieldName VARCHAR(); SET @fieldName=''; SELECT @fieldName = @fieldN ...
- 在SQL Server中 获取日期、日期格式转换
--常用日期转换参数: PRINT CONVERT(varchar, getdate(), 120 ) 2016-07-20 16:09:01 PRINT replace(replace(replac ...
- sql server 2005全角与半角字符转换
CREATE FUNCTION D_ByteExchangeS_Byte(@str NVARCHAR(4000), --要转换的字符串@flag bit --转换标志,0转换 ...
- SQL Server 一些使用小技巧
1.查询的时候把某一个字段的值拼接成字符串 以下是演示数据. 第一种方式:使用自定义变量 ) SET @Names='' -- 需要先赋值为空字符串,不然结果会是 null SELECT @Names ...
- Sql实现行列转换
从MS Sql Server 2005微软就推出了pivot和unpivot实现行列转换,这极大的方便了我们存储数据和呈现数据.今天就对这两个关键字进行分析,结合实例讲解如何存储数据,如何呈现数据. ...
随机推荐
- ubuntu16.04 安装 eclipse
1. 下载jdk , jdk-8u77-Linux-x64.tar.gz 2.下载 eclipse , eclipse-jee-mars-2-linux-gtk-x86_64.tar.gz 注:我下 ...
- AWS系列-添加购买的https证书
1.1 自行购买证书 1.2 上传证书 打开EC2的负载均衡 选择相应的ALB 添加侦听器 选择https 端口443 选择目标组 证书类型 上传证书到IAM 证书名称填写申请证书时候的那个域名 私有 ...
- MySQL------代码1024,can't get hostname for your address解决方法
1.hosts文件问题 进入C:\Windows\System32\drivers\etc\hosts 查看里面是否包含: # 127.0.0.1 localhost 没有则添加,再重启MySQL服务 ...
- iOS开发之--从URL加载图片
+ (UIImage *) imageFromURLString: (NSString *) urlstring { // This call is synchronous and blocking ...
- pushViewController自定义动画http://blog.csdn.net/ralbatr/article/details/22039233
本文转载至 http://blog.csdn.net/ralbatr/article/details/22039233 实现的主要代码如下: CATransition *transition = ...
- oracle的后台进程能否杀掉
oracle的后台进程杀掉会有什么影响 说明:本文复制自网友的博客: https://blog.csdn.net/kellyseeme/article/details/8927757 数据库版本为: ...
- eclipse控制台不限制显示的行数
在Preferences中搜索Console,设置Limit console output没有限制即可.
- java利用反射机制获取list中的某个字段并以list形式返回
public static<T> List<Object> listToList(Collection<T> list,String fieldName) thro ...
- CodeForces 24A Ring road(dfs)
A. Ring road time limit per test 2 seconds memory limit per test 256 megabytes input standard input ...
- MySQL数据库主从同步延迟分析及解决方案
一.MySQL的数据库主从复制原理 MySQL主从复制实际上基于二进制日志,原理可以用一张图来表示: 分为四步走: 1. 主库对所有DDL和DML产生的日志写进binlog: 2. 主库生成一个 lo ...