PIVOT就是行转列,UNPIVOT就是列传行
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 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语句和聚合查询。虽然这种方式让开发人员具有了对所返回数据进行高度控制的能力,但是编写出这些查询是一件很麻烦的事情。
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--别名一定要写
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就是列传行的更多相关文章
- sqlserver 行转列、字符串行转列、自动生产行转列脚本
行转列,老生常谈的问题.这里总结一下网上的方法. 1.生成测试数据: CREATE TABLE human( name ), --姓名 norm ), --指标 score INT , --分数 gr ...
- Oracle 行转列(不固定行数的行转列,动态)(转)
http://bbs.csdn.net/topics/330039676 SQLSERVER :行列转换例子: http://www.cnblogs.com/gaizai/p/3753296.htm ...
- SqlServer PIVOT函数快速实现行转列,UNPIVOT实现列转行
我们在写Sql语句的时候没经常会遇到将查询结果行转列,列转行的需求,拼接sql字符串,然后使用sp_executesql执行sql字符串是比较常规的一种做法.但是这样做实现起来非常复杂,而在SqlSe ...
- SqlServer PIVOT函数快速实现行转列,UNPIVOT实现列转行(转)
我们在写Sql语句的时候没经常会遇到将查询结果行转列,列转行的需求,拼接sql字符串,然后使用sp_executesql执行sql字符串是比较常规的一种做法.但是这样做实现起来非常复杂,而在SqlSe ...
- SqlServer 行转列,列转行 以及PIVOT函数快速实现行转列,UNPIVOT实现列转行
一 .列转行 创建所需的数据 CREATE TABLE [StudentScores]( [UserName] NVARCHAR(20), --学生姓名 [Subject] NVARCHAR(3 ...
- Pivot运算符用于在列和行之间
本文导读:T-SQL语句中,Pivot运算符用于在列和行之间对数据进行旋转或透视转换,PIVOT命令可以实现数据表的列转行,同时执行聚合运算,UNPIVOT则与其相反,实现数据的行转列. PIVOT通 ...
- SQL行转列和列转行
行列互转,是一个经常遇到的需求.实现的方法,有case when方式和2005之后的内置pivot和unpivot方法来实现. 在读了技术内幕那一节后,虽说这些解决方案早就用过了,却没有系统性的认识和 ...
- sql行转列和列转行(转)
行列互转,是一个经常遇到的需求.实现的方法,有case when方式和2005之后的内置pivot和unpivot方法来实现. 在读了技术内幕那一节后,虽说这些解决方案早就用过了,却没有系统性的认识和 ...
- mysql动态行转列
测试数据 DROP TABLE IF EXISTS `score`; CREATE TABLE `score` ( `id` ) NOT NULL AUTO_INCREMENT, `class` ) ...
随机推荐
- Pelican搭建静态博客
前言 一直以来都希望拥有属于自己的个人博客,随性发点信息,写点技术感想,记录自己的生活,重要的是不受广告的影响.不被河蟹.不会担心有一天被莫名其妙地消失. 之前看过一篇文章:"像黑客一样写博 ...
- GCD系列 之(二): 多核心的性能
全局队列的并发执行 for(id obj in array) [self doSomethingIntensiveWith:obj]; 假设,每个元素要做的事情-doSomethingIntensiv ...
- mac关机快捷键
1.Ctrl + 关机:弹出关机提示 2.Ctrl + Option + 关机 : 正常关机快捷键 3.Command + Option + 关机 :进入休眠状态 4.Ctrl + Command + ...
- Java Swing 记事本代码
记事本代码分为4个部分: 1.顶部点击可展开的菜单如何生成?2.当点击了顶部菜单的某一个子菜单,在程序中如何判断点击了哪个子菜单?[正在写]3.那个供你输入文字并且可以滚动的文本框如何生成?4.点击了 ...
- MySql表操作常用语法
检查表CHECK TABLE table_name;修复表REPAIR TABLE table_name;优化表OPTIMIZE TABLE table_name;分析表ANALYZE TABLE t ...
- MVC教程
http://developer.51cto.com/art/201309/409950_all.htm
- ndk搭建与运行
1)打开Android开发者的官网http://developer.android.com/找到Develop点击.如果页面打不开,通过代理来访问. 2)进入后再点击Tools 3)进入后在左侧找到N ...
- 3.Thread中的静态方法
1.currentThread() public class Thread14 extends Thread{ static { System.out.println("静态块的打印:&qu ...
- Linux终端快捷操作汇总
定位单词 在长段的命令中,使用 Ctrl + ← 和 Ctrl + → 可快速将光标定位到命令中单词的首字母或末尾,实现在各单词之间的快速跳动定位. 你可以试着在终端中输入 apt-get insta ...
- 记一次-angular-数字格式化
一个收费功能模块,需要做数据验证. input标签的ng-model的数据格式化 <input type="number" class="form-control& ...