来源:http://www.studyofnet.com/news/295.html

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

通俗简单的说:PIVOT就是行转列,UNPIVOT就是列传行

一、PIVOT实例

1. 建表

建立一个销售情况表,其中,year字段表示年份,quarter字段表示季度,amount字段表示销售额。quarter字段分别用Q1, Q2, Q3, Q4表示一、二、三、四季度。

 CREATE TABLE SalesByQuarter(    year INT,    -- 年份quarter CHAR(2),  -- 季度amount MONEY  -- 总额)

2. 填入表数据

使用如下程序填入表数据。

SET NOCOUNT ONDECLARE @index INTDECLARE @q INTSET @index = 0DECLARE @year INTwhile (@index < 30)BEGINSET @year = 2005 + (@index % 4)SET @q = (CAST((RAND() * 500) AS INT) % 4) + 1INSERT INTO SalesByQuarter VALUES (@year, 'Q' + CAST(@q AS CHAR(1)), RAND() * 10000.00)SET @index = @index + 1END

3、如果我们要比较每年中各季度的销售状况,要怎么办呢?有以下两种方法:

(1)、使用传统Select的CASE语句查询

在SQL Server以前的版本里,将行级数据转换为列级数据就要用到一系列CASE语句和聚合查询。虽然这种方式让开发人员具有了对所返回数据进行高度控制的能力,但是编写出这些查询是一件很麻烦的事情。

            SELECT year as 年份, sum (case when quarter = 'Q1' then amount else 0 end) 一季度, sum (case when quarter = 'Q2' then amount else 0 end) 二季度, sum (case when quarter = 'Q3' then amount else 0 end) 三季度, sum (case when quarter = 'Q4' then amount else 0 end) 四季度FROM SalesByQuarter GROUP BY year ORDER BY year DESC

得到的结果如下:

(2)、使用PIVOT

由于SQL Server 2005有了新的PIVOT运算符,就不再需要CASE语句和GROUP BY语句了。(每个PIVOT查询都涉及某种类型的聚合,因此你可以忽略GROUP BY语句。)PIVOT运算符让我们能够利用CASE语句查询实现相同的功能,但是你可以用更少的代码就实现,而且看起来更漂亮。

SELECT year as 年份, Q1 as 一季度, Q2 as 二季度, Q3 as 三季度, Q4 as 四季度 FROM SalesByQuarter PIVOT (SUM (amount) FOR quarter IN (Q1, Q2, Q3, Q4) ) AS P ORDER BY YEAR DESC

得到的结果如下:

二、通过下面一个实例详细介绍PIVOT的过程

SELECT [星期一],[星期二],[星期三],[星期四],[星期五],[星期六],[星期日]--这里是PIVOT第三步(选择行转列后的结果集的列)这里可以用“*”表示选择所有列,也可以只选择某些列(也就是某些天)
FROM WEEK_INCOME --这里是PIVOT第二步骤(准备原始的查询结果,因为PIVOT是对一个原始的查询结果集进行转换操作,所以先查询一个结果集出来)这里可以是一个select子查询,但为子查询时候要指定别名,否则语法错误
PIVOT
(SUM(INCOME) for [week] in([星期一],[星期二],[星期三],[星期四],[星期五],[星期六],[星期日])--这里是PIVOT第一步骤,也是核心的地方,进行行转列操作。聚合函数SUM表示你需要怎样处理转换后的列的值,是总和(sum),还是平均(avg)还是min,max等等。例如如果week_income表中有两条数据并且其week都是“星期一”,其中一条的income是1000,另一条income是500,那么在这里使用sum,行转列后“星期一”这个列的值当然是1500了。后面的for [week] in([星期一],[星期二])中 for [week]就是说将week列的值分别转换成一个个列,也就是“以值变列”。但是需要转换成列的值有可能有很多,我们只想取其中几个值转换成列,那么怎样取呢?就是在in里面了,比如我此刻只想看工作日的收入,在in里面就只写“星期一”至“星期五”(注意,in里面是原来week列的值,"以值变列")。总的来说,SUM(INCOME) for [week] in([星期一],[星期二],[星期三],[星期四],[星期五],[星期六],[星期日])这句的意思如果直译出来,就是说:将列[week]值为"星期一","星期二","星期三","星期四","星期五","星期六","星期日"分别转换成列,这些列的值取income的总和。
)TBL--别名一定要写

三.UNPIVOT
很明显,UN这个前缀表明了,它做的操作是跟PIVOT相反的,即列转行。UNPIVOT操作涉及到以下三个逻辑处理阶段。
1,生成副本
2,提取元素
3,删除带有NULL的行
UNPIVOT实例
 
CREATE TABLE pvt (VendorID int, Emp1 int, Emp2 int,Emp3 int, Emp4 int, Emp5 int);
GO
INSERT INTO pvt VALUES (1,4,3,5,4,4);
INSERT INTO pvt VALUES (2,4,1,5,5,5);
INSERT INTO pvt VALUES (3,4,3,5,4,4);
INSERT INTO pvt VALUES (4,4,2,5,5,4);
INSERT INTO pvt VALUES (5,5,1,5,5,5);
GO
--Unpivot the table.
SELECT VendorID, Employee, Orders
FROM (SELECT VendorID, Emp1, Emp2, Emp3, Emp4, Emp5FROM pvt) p
UNPIVOT(Orders FOR Employee IN (Emp1, Emp2, Emp3, Emp4, Emp5)
)AS unpvt;
GO

上面UNPIVOT实例的分析

UNPIVOT的输入是左表表达式P,第一步,先为P中的行生成多个副本,在UNPIVOT中出现的每一列,都会生成一个副本。因为这里的IN子句有5个列名称,所以要为每个来源行生成5个副本。结果得到的虚拟表中将新增一个列,用来以字符串格式保存来源列的名称(for和IN之间的,上面例子是 Employee )。第二步,根据新增的那一列中的值从来源列中提取出与列名对应的行。第三步,删除掉结果列值为null的行,完成这个查询。

------------------------------------------------------------------------------------

来源 http://blog.sina.com.cn/s/blog_407d66af0100b4s7.html

普通行列转换
问题:假设有张学生成绩表(tb)如下:
姓名 课程 分数
张三 语文 74
张三 数学 83
张三 物理 93
李四 语文 74
李四 数学 84
李四 物理 94
想变成(得到如下结果):
姓名 语文 数学 物理
---- ---- ---- ----
李四 74   84   94
张三 74   83   93
-------------------
*/

create table tb(姓名 varchar(10) , 课程 varchar(10) , 分数 int)
insert into tb values('张三' , '语文' , 74)
insert into tb values('张三' , '数学' , 83)
insert into tb values('张三' , '物理' , 93)
insert into tb values('李四' , '语文' , 74)
insert into tb values('李四' , '数学' , 84)
insert into tb values('李四' , '物理' , 94)
go--SQL SERVER 2000 静态SQL,指课程只有语文、数学、物理这三门课程。(以下同)
select 姓名 as 姓名 ,max(case 课程 when '语文' then 分数 else 0 end) 语文,max(case 课程 when '数学' then 分数 else 0 end) 数学,max(case 课程 when '物理' then 分数 else 0 end) 物理
from tb
group by 姓名--SQL SERVER 2000 动态SQL,指课程不止语文、数学、物理这三门课程。(以下同)
declare @sql varchar(8000)
set @sql = 'select 姓名 '
select @sql = @sql + ' , max(case 课程 when ''' + 课程 + ''' then 分数 else 0 end) [' + 课程 + ']'
from (select distinct 课程 from tb) as a
set @sql = @sql + ' from tb group by 姓名'
exec(@sql)--SQL SERVER 2005 静态SQL。
select * from (select * from tb) a pivot (max(分数) for 课程 in (语文,数学,物理)) b--SQL SERVER 2005 动态SQL。
declare @sql varchar(8000)
select @sql = isnull(@sql + ',' , '') + 课程 from tb group by 课程
exec ('select * from (select * from tb) a pivot (max(分数) for 课程 in (' + @sql + ')) b')

转载于:https://www.cnblogs.com/zouhao/p/6050809.html

SQL中PIVOT 行列转换相关推荐

  1. SQL Server pivot行列转换案例分析

    通过Pivot进行行列转换 需求描述 需求:如果我们对订单表(Sales.Orders)里的客户编号(cust_id)以不同的货船编号(shipperid)为列,其对应的费用(freight)求和为值 ...

  2. mysql中的行列转换

    mysql中的行列转换 案例:1 两张表合成一张表统计各个分类的总数. 建表语句 # doc表建表语句 SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; - ...

  3. 关于SQL中PIVOT函数的使用方法

    文章目录 前言 一.关于PIVOT函数    1.什么是PIVOT函数 2.它能实现什么样的效果 二.使用方法 三.使用前后的效果 总结 前言 这篇文章给大家分享的是"pivot函数是什么, ...

  4. SQL中PIVOT的用法

    PIVOT 提供的语法比一系列复杂的 SELECT-CASE 语句中所指定的语法更简单和更具可读性. 以下是带批注的 PIVOT 语法: SELECT <非透视的列>,[第一个透视的列] ...

  5. [转] SQL Server中的行列转换问题

    原表结构 序号 性别 部门 工资 1 男 部门a 800 2 女 部门b 900 3 男 部门a 400 4 女 部门d  1400 5 男 部门e 1200 6 男 部门f 500 7 女 部门a  ...

  6. sql中数据类型的转换(自己写比较累哈,偷偷懒,转下别人的)

    CAST 和 CONVERT 提供的功能:将某种数据类型的表达式显式转换为另一种数据类型. 语法 使用 CAST: CAST ( expression AS data_type ) 使用 CONVER ...

  7. Sql中的格式转换功能

    前言 小编最近在项目中学习大佬们的代码,看到sql查询语句跟我见过的有些不一样,我就知道学习的机会又来了. 正文 Sql Server中的格式转换功能 Sql语句中常用的类型转换函数主要有两种,Cas ...

  8. Sql 中常用日期转换Convert(Datetime)

    CONVERT(data_type,expression[,style])  convert(varchar(10),字段名,转换格式) 说明: 此样式一般在时间类型(datetime,smallda ...

  9. (转)Oracle中实现行列转换的方法

    (转自)http://blog.csdn.net/Torrice/archive/2006/01/25/587986.aspx 我们在写SQL语句的时候经常需要用到行与列的转换问题,对于一个新手来说可 ...

最新文章

  1. [译] ASP.NET 生命周期 – ASP.NET 上下文对象(六)
  2. Java 16 正式发布!你还学得动吗?
  3. python urllib的用法实例
  4. callapplybind的js实现以及应用
  5. GridView 激发了未处理的事件“RowEditing”
  6. 【转】图形流水线中坐标变换详解:模型矩阵、视角矩阵、投影矩阵
  7. iscroll的使用
  8. .Net程序员学习Linux最简单的方法(转载)
  9. 解决shell脚本“syntax error near unexpected token `fi‘”的问题。
  10. 《Visual C# 从零开始学》
  11. 什么是反射,为什么要用反射,反射的知识讲解
  12. netty心跳功能机制实现
  13. mac 文字识别软件ocr_树洞OCR文字识别for Mac-树洞OCR文字识别Mac版下载 V1.2.0-PC6苹果网...
  14. mysql有多少个端口号_mysql默认端口号(mysql端口号是多少)
  15. 闪存flash基础原理
  16. 词法分析器的java代码_利用Java实现简单的词法分析器实例代码
  17. mpp的文件要下载什么来打开
  18. SVN报错Skipped ‘xxxController.class.php‘ -- Node remains in conflict
  19. Android Sendor框架介绍
  20. 黄金分割法求函数最小值

热门文章

  1. shell命令总结3
  2. 高手进阶:/etc/profile环境变量配置解析
  3. kill不掉 spark-submit
  4. jupyter notebook报错Failed to load module appmenu-gtk-module
  5. join操作-内联,左外联,右外联,交叉联,全联
  6. Xception论文阅读笔记
  7. Transifex与GTK文档翻译, Linux镜像文件, 外设接口杂谈
  8. chrome调试js的小技巧
  9. LVS:三种负载均衡方式比较
  10. 记录使用websocket时因为Sec-Websocket-Protocol遇到的一个问题