对于行列转换的数据,通常也就是在做报表的时候用的比较多,之前也零零散散的看了一些,今天就来总结一下。

先创建一个用于演示的临时表:

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

最新文章

  1. CouchDB简介
  2. php curl用法
  3. 今天网站后台登录页面需要生成一个二维码,然后在手机app上扫描这个二维码,实现网站登录的效果及其解决方案如下
  4. JavaScript精要
  5. androidstudio 之 svn配置 汇总
  6. Dynamic CRM 2013学习笔记(四十五)修改实体及字段的前缀(不用new_开头)
  7. 关于CAShapeLayer的一些实用案例和技巧
  8. 仿AS语法来写HTML5—第1章,显示一张图片
  9. ActiveMQ(5.10.0) - Connection Configuration URI
  10. Linux安装Git
  11. handsontable的核心方法
  12. TCP/IP详解之:ARP协议 和 RARP协议
  13. 关于WannaCry病毒的见解与预防,我有话说!
  14. hdu 5700区间交(线段树)
  15. IDEA进行远程调试
  16. JS实现购物车01
  17. HDU 1232 畅通工程 (并查集)
  18. 微软Power BI 每月功能更新系列——8月Power BI 新功能学习
  19. jQuery函数继承 $.extend, $.fn.extend
  20. CloseableHttpClient与 CloseableHttpResponse应用

热门文章

  1. maven+springmvc错误 JAX-RS (REST Web Services) 2.0 can not be installed
  2. Node.js的全局对象和全局变量
  3. python3----练习题(图片转字符画)
  4. CreateRemoteThreadex开启远程线程失败集合
  5. github &#39;s usage
  6. C++编译遇到参数错误(cannot convert parameter * from &#39;const char [**]&#39; to &#39;LPCWSTR&#39;)
  7. 后端程序员如何玩转AJAX
  8. requireJs官方使用教程(转)
  9. 160616、jQuery插件之ajaxFileUpload及jqueryeasyui学习资料分享
  10. Spoken English Practice(Don&#39;t get me wrong, that explanation makes no difference, I&#39;m still mad at you. Come on, be reasonable!)