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

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

一、PIVOT实例

1. 建表

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

 
SQL 代码   复制

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

2. 填入表数据

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

 
SQL 代码   复制

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

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

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

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

 
SQL 代码   复制

    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语句查询实现相同的功能,但是你可以用更少的代码就实现,而且看起来更漂亮。

 
SQL 代码   复制

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的过程

 
SQL 代码   复制

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实例
 
 
SQL 代码   复制

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, Emp5
FROM 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://www.studyofnet.com/news/295.html

PIVOT就是行转列,UNPIVOT就是列传行的更多相关文章

  1. sqlserver 行转列、字符串行转列、自动生产行转列脚本

    行转列,老生常谈的问题.这里总结一下网上的方法. 1.生成测试数据: CREATE TABLE human( name ), --姓名 norm ), --指标 score INT , --分数 gr ...

  2. Oracle 行转列(不固定行数的行转列,动态)(转)

    http://bbs.csdn.net/topics/330039676 SQLSERVER :行列转换例子:  http://www.cnblogs.com/gaizai/p/3753296.htm ...

  3. SqlServer PIVOT函数快速实现行转列,UNPIVOT实现列转行

    我们在写Sql语句的时候没经常会遇到将查询结果行转列,列转行的需求,拼接sql字符串,然后使用sp_executesql执行sql字符串是比较常规的一种做法.但是这样做实现起来非常复杂,而在SqlSe ...

  4. SqlServer PIVOT函数快速实现行转列,UNPIVOT实现列转行(转)

    我们在写Sql语句的时候没经常会遇到将查询结果行转列,列转行的需求,拼接sql字符串,然后使用sp_executesql执行sql字符串是比较常规的一种做法.但是这样做实现起来非常复杂,而在SqlSe ...

  5. SqlServer 行转列,列转行 以及PIVOT函数快速实现行转列,UNPIVOT实现列转行

     一   .列转行 创建所需的数据 CREATE TABLE [StudentScores]( [UserName] NVARCHAR(20), --学生姓名 [Subject] NVARCHAR(3 ...

  6. Pivot运算符用于在列和行之间

    本文导读:T-SQL语句中,Pivot运算符用于在列和行之间对数据进行旋转或透视转换,PIVOT命令可以实现数据表的列转行,同时执行聚合运算,UNPIVOT则与其相反,实现数据的行转列. PIVOT通 ...

  7. SQL行转列和列转行

    行列互转,是一个经常遇到的需求.实现的方法,有case when方式和2005之后的内置pivot和unpivot方法来实现. 在读了技术内幕那一节后,虽说这些解决方案早就用过了,却没有系统性的认识和 ...

  8. sql行转列和列转行(转)

    行列互转,是一个经常遇到的需求.实现的方法,有case when方式和2005之后的内置pivot和unpivot方法来实现. 在读了技术内幕那一节后,虽说这些解决方案早就用过了,却没有系统性的认识和 ...

  9. mysql动态行转列

    测试数据 DROP TABLE IF EXISTS `score`; CREATE TABLE `score` ( `id` ) NOT NULL AUTO_INCREMENT, `class` ) ...

随机推荐

  1. Facebook 在page添加自己开发的app

    最初接到的需求是,在facebook主页中嵌入一个类似这样领取游戏礼包的页面. 一开始连facebook开发者中心在哪里都不知道,在万能的搜索框里面找到static html之类的第三方应用,但是这样 ...

  2. 一个快速、高效的Levenshtein算法实现——代码实现

    在网上看到一篇博客讲解Levenshtein的计算,大部分内容都挺好的,只是在一些细节上不够好,看了很长时间才明白.我对其中的算法描述做了一个简单的修改.原文的链接是:一个快速.高效的Levensht ...

  3. Java的关键字和标识符

    1.关键字 Java中共有52个关键字,其中有两个保留字,虽然查到百度百科上说是50个,但是事实确实是有52个(47+3+2). 1.1保留字 Java语言的的保留字是指在Java中商务预留的关键字 ...

  4. underScore学习1:匿名函数中call(this)的作用

    匿名函数中(function(){}).call(this) 中的.call(this) 有什么用? 我们都知道,.call()可以改变函数执行时的context,即this的指向,源码中的.call ...

  5. wpf 控件截屏

    /// <summary> /// 保存截图 /// </summary> /// <param name="ui">控件名称</para ...

  6. python demo整理

    1 变量作用域 #!/usr/bin/python # coding=utf-8 name = "whole global name" class Person: name = & ...

  7. 中小型公司数据仓库搭建——以mysql为例

    为了方便公司的数据分析平台的独立运行和数据挖掘的探索,今年上半年在公司搭建了支持数据平台和数据挖掘的数据仓库:现就数据仓库的创建工作总结如下,供大家参考: 首先介绍下数据仓库搭建的缘由: 公司创建两年 ...

  8. mongodb 性能提高之利用索引, 待续

    > 10 , 用户无法忍受 >1s , 需要加装中提示 数据库对软件整体影响是不言而喻的, 那么使用 MOngoDB时 该如何提高数据库性能 第一: 索引, 相当于记忆法的 地点桩 1. ...

  9. 【c++】size_t 和 size_type的区别

    为了使自己的程序有很好的移植性,c++程序员应该尽量使用size_t和size_type而不是int, unsigned 1. size_t是全局定义的类型:size_type是STL类中定义的类型属 ...

  10. hibernate异常:org.hibernate.exception.GenericJDBCException

    异常:org.hibernate.exception.GenericJDBCException 提示:Cannot open connection 提示:不能打开链接 一般这个异常是由 java.sq ...