SQL Server 使用 Pivot 和 UnPivot 实现行列转换的问题小结

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

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

create table #temp
(
    年份    nvarchar(10)    null,
    月份    nvarchar(10)    null,
    数量    int        null
)
insert into #temp(年份,月份,数量)
select '2015','1','5645' union
select '2015','2','1234' union
select '2015','3','7982' union
select '2016','1','6465' union
select '2016','2','7942' union
select '2016','3','8453' union
select '2017','1','4653' union
select '2017','2','1358' union
select '2017','3','7842'
select * from #temp

下面来实现一些需求:

需求一,按年份分组,不同的月份为一列。

-- 按年份分组,不同的月份为一列
select t.年份,
sum(case t.月份 when '1' then t.数量 end) '1月份',
sum(case t.月份 when '2' then t.数量 end) '2月份',
sum(case t.月份 when '3' 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 月份='1') t1 on t.年份=t1.年份
left join (select 年份,数量 from #temp where 月份='2') t2 on t.年份=t2.年份
left join (select 年份,数量 from #temp where 月份='3') 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 月份='1') t1,
(select 年份,数量 from #temp where 月份='2') t2,
(select 年份,数量 from #temp where 月份='3') 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 '小李','语文','88' union
select '小李','数学','79' union
select '小李','英语','85' union
select '小明','语文','79' union
select '小明','数学','89' union
select '小明','英语','87' union
select '小红','语文','84' union
select '小红','数学','76' union
select '小红','英语','92'
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(语文,数学,英语)    -- 自定义的目标列名,即要转换列的不同的值作为列
)

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 '小李','88','79','85' union
select '小明','79','89','87' union
select '小红','84','76','92'
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)
)

到此这篇关于SQL Server 使用 Pivot 和 UnPivot 实现行列转换的文章就介绍到这了,更多相关SQL Server行列转换内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • sql server通过pivot对数据进行行列转换的方法

    脚本: /* 说明:sql server如何通过pivot对数据进行行列转换 */ create table #t ( [员工工号] nvarchar(50), [员工姓名] nvarchar(50), [月份] nvarchar(50), [工资] int ) insert into #t values(N'01', N'张三', N'2020年01月', 2400) ,(N'02', N'李四', N'2020年01月', 3000) ,(N'01', N'张三', N'2020年02月',

  • sqlserver2005 行列转换实现方法

    复制代码 代码如下: --Create Company Table Create Table Company ( ComID varchar(50) primary key, ComName nvarchar(50) not null, ComNumber varchar(50) not null, ComAddress nvarchar(200), ComTele varchar(50) ) --Create Product Table Create Table Product ( Produ

  • 行转列之SQL SERVER PIVOT与用法详解

    在数据库操作中,有些时候我们遇到需要实现"行转列"的需求,例如一下的表为某店铺的一周收入情况表: WEEK_INCOME(WEEK VARCHAR(10),INCOME DECIMAL) 我们先插入一些模拟数据: INSERT INTO WEEK_INCOME SELECT '星期一',1000 UNION ALL SELECT '星期二',2000 UNION ALL SELECT '星期三',3000 UNION ALL SELECT '星期四',4000 UNION ALL SE

  • SQL Server 使用 Pivot 和 UnPivot 实现行列转换的问题小结

    对于行列转换的数据,通常也就是在做报表的时候用的比较多,之前也零零散散的看了一些,今天就来总结一下. 先创建一个用于演示的临时表: create table #temp ( 年份 nvarchar(10) null, 月份 nvarchar(10) null, 数量 int null ) insert into #temp(年份,月份,数量) select '2015','1','5645' union select '2015','2','1234' union select '2015','

  • SQL Server使用PIVOT与unPIVOT实现行列转换

    一.sql行转列:PIVOT 1.基本语法: create table #table1 ( id int ,code varchar(10) , name varchar(20) ); go insert into #table1 ( id,code, name ) values ( 1, 'm1','a' ), ( 2, 'm2',null ), ( 3, 'm3', 'c' ), ( 4, 'm2','d' ), ( 5, 'm1','c' ); go select * from #tabl

  • Sql实现行列转换方便了我们存储数据和呈现数据

    从MS Sql Server 2005微软就推出了pivot和unpivot实现行列转换,这极大的方便了我们存储数据和呈现数据.今天就对这两个关键字进行分析,结合实例讲解如何存储数据,如何呈现数据. 例如学生选课和成绩系统中就有一张表,该表存储了学生的课程成绩,我们无法去预料课程的多少,因此一般表会设计为下面这样: 图1  最后一列是课程编号,这样无论开学之后还会不会增加课程供学生选择,都没有关系.那么我们要呈现给用户看的报表一般是这样的: 图2  可以看到存储数据的时候采用的是列式存储,最终呈

  • asp.net开发sql server转换成oracle的方法详解

    前言 因为前段时间我们公司项目 要把sql server 转oracle,发现网上这方面的资料较少,所以在这里分享一下心得,也记录一下问题,下面话不多说了,来一起看看详细的介绍: 开始我研究了一段时间 然后下载了 oracle 11g 版本 和 PL/SQL(客户端) 和sql server 不同的是 oracle 没有自己的客户端 需要用第三方的软件运行 PL/SQL 就是一个 sqldeveloper 也是一个,PL/SQL 我觉得比较稳定一点.但是2个都安装的话 刚好互补了 oracle

  • SQL Server数据类型转换方法

    在SQL Server日常的函数.存储过程和SQL语句中,经常会用到不同数据类型的转换.在SQL Server有两种数据转换类型:一种是显性数据转换:另一种是隐性数据转换.下面分别对这两种数据类型转换进行简要的说明: 1 显式转换 显示转换是将某种数据类型的表达式显式转换为另一种数据类型.常用的是CAST 和 CONVERT 函数. CAST: CAST ( expression AS data_type )  CONVERT: CONVERT (data_type[(length)], exp

  • 深入SQL中PIVOT 行列转换详解

    PIVOT通过将表达式某一列中的唯一值转换为输出中的多个列来旋转表值表达式,并在必要时对最终输出中所需的任何其余列值执行聚合.UNPIVOT与PIVOT执行相反的操作,将表值表达式的列转换为列值. 通俗简单的说:PIVOT就是行转列,UNPIVOT就是列传行 一.PIVOT实例 1. 建表 建立一个销售情况表,其中,year字段表示年份,quarter字段表示季度,amount字段表示销售额.quarter字段分别用Q1, Q2, Q3, Q4表示一.二.三.四季度. CREATE TABLE

  • 浅析SQL语句行列转换的两种方法 case...when与pivot函数的应用

    /*创建数据库*/ CREATE DATABASE tmp go USE tmp go /*创建数据库测试表*/ CREATE TABLE [Scores]     (       [ID] INT IDENTITY(1, 1)                PRIMARY KEY ,       [Student] VARCHAR(20) ,       [Subject] VARCHAR(30) ,       [Score] FLOAT     ) go TRUNCATE TABLE Sc

  • SQL Server 2008的逻辑查询处理步骤

    最近我则刚刚收到了微软最有价值专家项目组寄来的该书的SQL Server 2008英文版本-<Inside Microsoft SQL Server 2008:T-SQL Querying>(http://www.microsoft.com/learning/en/us/book.aspx?ID=12804&locale=en-us),大致翻了一下,发现内容变动不少,既有新增的章节,也有基于SQL Server 2005或2008新技术重新书写的SQL查询示例. 我先就逻辑查询处理步骤

随机推荐