[转]Oracle SQL函数pivot、unpivot转置函数实现行转列、列转行
原文地址:http://blog.csdn.net/seandba/article/details/72730657
函数PIVOT、UNPIVOT转置函数实现行转列、列转行,效果如下图所示:
1.PIVOT为行转列,从图示的左边到右边
2.UNPIVOT为列转行,从图示的右边到左边
3.左边为纵表,结构简单,易扩展
4.右边为横表,展示清晰,方便查询
5.很多时候业务表为纵表,但是统计分析需要的结果如右边的横表,这时候就需要用到转置函数了
示例图表:
Pivot语法:
- SELECT ....
- FROM <table-expr>
- PIVOT
- (
- aggregate-function(<column>)
- FOR <pivot-column> IN (<value1>, <value2>,..., <valuen>)
- ) AS <alias>
- WHERE .....
注意:
- FOR <pivot-column>
这个是不支持表达式的,如果需要,请通过子查询或者视图先预处理。
Pivot
例子1:先构造一个子查询,然后根据CHANNEL列进行转置,源表sales_view里面可能有很多列,不需要列先通过子查询过滤掉再进行转置。
另外转置后的列指定了别名,值是对amount_sold列的汇总。
- SELECT * FROM
- (SELECT product, channel, amount_sold
- FROM sales_view
- ) S PIVOT (SUM(amount_sold)
- FOR CHANNEL IN (3 AS DIRECT_SALES, 4 AS INTERNET_SALES,
- 5 AS CATALOG_SALES, 9 AS TELESALES))
- ORDER BY product;
- PRODUCT DIRECT_SALES INTERNET_SALES CATALOG_SALES TELESALES
- ---------------------- ------------ -------------- ------------- ---------
- ...
- Internal 6X CD-ROM 229512.97 26249.55
- Internal 8X CD-ROM 286291.49 42809.44
- Keyboard Wrist Rest 200959.84 38695.36 1522.73
- ...
例子2:基于多列进行转置,下面例子是基于channel、quarter两列进行转置
- SELECT *
- FROM
- (SELECT product, channel, quarter, quantity_sold
- FROM sales_view
- ) PIVOT (SUM(quantity_sold)
- FOR (channel, quarter) IN
- ((5, '02') AS CATALOG_Q2,
- (4, '01') AS INTERNET_Q1,
- (4, '04') AS INTERNET_Q4,
- (2, '02') AS PARTNERS_Q2,
- (9, '03') AS TELE_Q3
- )
- );
- PRODUCT CATALOG_Q2 INTERNET_Q1 INTERNET_Q4 PARTNERS_Q2 TELE_Q3
- ------- ---------- ----------- ----------- ----------- -------
- ...
- Bounce 347 632 954
- ...
- Smash Up Boxing 129 280 560
- ...
- Comic Book Heroes 47 155 275
- ...
例子3:对多列的值进行汇总计算,以下是基于channel例进行转置,然后对amount_sold和quantity_sold两列进行合计运算
- SELECT *
- FROM
- (SELECT product, channel, amount_sold, quantity_sold
- FROM sales_view
- ) PIVOT (SUM(amount_sold) AS sums,
- SUM(quantity_sold) AS sumq
- FOR channel IN (5, 4, 2, 9)
- )
- ORDER BY product;
- PRODUCT 5_SUMS 5_SUMQ 4_SUMS 4_SUMQ 2_SUMS 2_SUMQ 9_SUMS 9_SUMQ
- ------------- ------ ------ ------ ------ ------ ------ ------ ------
- O/S Doc Set English 142780.36 3081 381397.99 8044 6028.66 134
- O/S Doc Set French 55503.58 1192 132000.77 2782
- ...
Unpivot
unpivot是pivot的相反操作,进行的是列转行
例子1:先看源表结构,for子句指定将(Q1_SUMQ, Q2_SUMQ, Q3_SUMQ, Q4_SUMQ)这4列转置为行,
for子句之前的quantity_sold是4列转置后的列名,
decode还定义了每列转置为行后新标示列的值,这个等下看第2个例子可以看到,也可以在 in 子句后面加 as 指定别名。
UNPIVOT INCLUDE NULLS 指定空值也进行转置,如果是EXCLUDE NULLS 将忽略空值。
- SELECT *
- FROM pivotedTable
- ORDER BY product;
- PRODUCT Q1_SUMQ Q1_SUMA Q2_SUMQ Q2_SUMA Q3_SUMQ Q3_SUMA Q4_SUMQ Q4_SUMA
- --------------- ------- ------- ------- -------- ------- -------- ------- ---------
- 1.44MB External 6098 58301.33 5112 49001.56 6050 56974.3 5848 55341.28
- 128MB Memory 1963 110763.63 2361 132123.12 3069 170710.4 2832 157736.6
- 17" LCD 1492 1812786.94 1387 1672389.06 1591 1859987.66 1540 1844008.11
- SELECT product, DECODE(quarter, 'Q1_SUMQ', 'Q1', 'Q2_SUMQ', 'Q2', 'Q3_SUMQ', 'Q3',
- 'Q4_SUMQ', 'Q4') AS quarter, quantity_sold
- FROM pivotedTable
- UNPIVOT INCLUDE NULLS
- (quantity_sold
- FOR quarter IN (Q1_SUMQ, Q2_SUMQ, Q3_SUMQ, Q4_SUMQ))
- ORDER BY product, quarter;
- PRODUCT QUARTER QUANTITY_SOLD
- ------- -- -------------
- 1.44MB External 3.5" Diskette Q1 6098
- 1.44MB External 3.5" Diskette Q2 5112
- 1.44MB External 3.5" Diskette Q3 6050
- 1.44MB External 3.5" Diskette Q4 5848
- 128MB Memory Card Q1 1963
- 128MB Memory Card Q2 2361
- 128MB Memory Card Q3 3069
- 128MB Memory Card Q4 2832
- ...
例子2:转置多列的情况
- SELECT product, quarter, quantity_sold, amount_sold
- FROM pivotedTable
- UNPIVOT INCLUDE NULLS
- (
- (quantity_sold, amount_sold)
- FOR quarter IN ((Q1_SUMQ, Q1_SUMA) AS 'Q1', (Q2_SUMQ, Q2_SUMA) AS 'Q2', (Q3_SUMQ, Q3_SUMA) AS 'Q3', (Q4_SUMQ, Q4_SUMA) AS 'Q4'))
- ORDER BY product, quarter;
- PRODUCT QU QUANTITY_SOLD AMOUNT_SOLD
- ----------------------------- -- ------------- ------------
- 1.44MB External 3.5" Diskette Q1 6098 58301.33
- 1.44MB External 3.5" Diskette Q2 5112 49001.56
- 1.44MB External 3.5" Diskette Q3 6050 56974.3
- 1.44MB External 3.5" Diskette Q4 5848 55341.28
- 128MB Memory Card Q1 1963 110763.63
- 128MB Memory Card Q2 2361 132123.12
- 128MB Memory Card Q3 3069 170710.4
- 128MB Memory Card Q4 2832 157736.6
总结,基本上按照语法套用即可,注意将源表非相关列先过滤掉,可是是子查询,也可以是视图。
最后试试解决这个问题吧,看你是否真的懂了!
http://blog.csdn.net/seandba/article/details/72629724
以上内容均来自Oracle11g官方文档,我只是搬运工。。。
Oracle® Database Data Warehousing Guide
11g Release 2 (11.2)
E25554-01
[转]Oracle SQL函数pivot、unpivot转置函数实现行转列、列转行的更多相关文章
- Oracle SQL常用内置系统函数总结
Oracle数据库 内置系统函数主要分为以下类别:数学函数.字符串函数.日期函数.转换函数.聚合函数.分析聚合函数 一.数学函数 ------------返回数字 abs(n):返回数字 ...
- Oracle SQL Lesson (5) - 使用组函数输出聚合数据
组函数AVGCOUNTMAXMINSUMVARIANCE:方差STDDEV:标准差 SELECT AVG(salary), MAX(salary), MIN(salary), SUM(salary)F ...
- Oracle SQL Lesson (3) - 使用单行函数自定义输出
大小写转换函数LOWER('SQL Course') = sql courseUPPER('SQL Course') = SQL COURSEINITCAP('SQL Course') = Sql C ...
- Oracle SQL Lesson (4) - 使用转换函数和条件表达式
隐式转换select * from emp where empno='7788'字符(char,varchar2)转换为数字(number)或日期(date)数字或日期转换为字符 显式转换字符转换为数 ...
- sql server pivot/unpivot 行列互转
有时候会碰到行转列的需求(也就是将列的值作为列名称),通常我都是用 CASE END + 聚合函数来实现的. 如下: declare @t table (StudentName nvarchar(20 ...
- sql:pivot unpivot
pivot 行转列 unpivot 列转行 源码跑步起来 这是能跑起来的 源码转自 http://www.cnblogs.com/zhangzt/archive/2010/07/29/178782 ...
- 问题:PLS-00204: 函数或伪列 'EXISTS' 只能在 SQL 语句中使用;结果:PL/SQL中不能用exists函数?
怎么写了一个语句带出这样的结果. 语句: if exists (select * from sysdatabases where name='omni') then 结果: ERROR 位于第 4 行 ...
- Oracle 行列转换函数pivot、unpivot的使用(二)
一.行转列pivot 关键函数pivot,其用法如下 pivot(聚合函数 for 列名 in(类型)) select * from table_name pivot(max(column_name) ...
- Oracle行转列,pivot函数和unpivot函数
pivot函数:行转列函数: 语法:pivot(任一聚合函数 for 需专列的值所在列名 in (需转为列名的值)):unpivot函数:列转行函数: 语法:unpivot(新增值所在列的列名 for ...
随机推荐
- 会动的Tabbar
项目搭建 一.设计模式首先呢,小Q采用传统的MVC的设计模式,优点我们再来啰嗦一下啊:1.多个视图可以对应一个模型.按MVC设计模式,一个模型对应多个视图,可以减少代码的复制及代码的维护量,一旦模型发 ...
- [企业化NET]Window Server 2008 R2[2]-SVN 服务端 和 客户端 安装
1. 服务器基本安装即问题解决记录 √ 2. SVN环境搭建和客户端使用 2.1 服务端 和 客户端 安装 √ 2.2 项目建立与基本使用 √ 2.3 基本冲突解决, ...
- The password supplied with the username Domain\UserName was not correct. Verify that it was entered correctly and try again
起因 今天想进入SharePoint 2013 Central Administration创建一个WebApplication,尽然发生了错误: The password supplied with ...
- Java 内存溢出思维导图
文 by / 林本托 Tips 做一个终身学习的人. 在 Java 内存中,只有一个区域不会发生 OOM 异常,那就是程序计数器内存.下面的思维导图记录了每个内存区域发生内存异常的条件和基本的解决思路 ...
- Markdown 使用教程
前言 以前经常在 github 中看到 .md 格式的文件,一直没有注意,也不明白为什么文本文档的后缀不是 .txt ,后来无意中看到了 Markdown,看到了用这个东西写得一些web界面等特别的规 ...
- OLTP和OLAP有何区别?
OLTP即联机事务处理,就是我们经常说的关系数据库,意即记录即时的增.删.改.查,就是我们经常应用的东西,这是数据库的基础:OLAP即联机分析处理,是数据仓库的核心部心,所谓数据仓库是对于大量已经由O ...
- 安卓listview滚动时背景变黑的解决方法
ListView是常用的显示控件,默认背景是和系统窗口一样的透明色,如果给ListView加上背景图片,或者背景颜色时,滚动时listView会黑掉, 原因是,滚动时,列表里面的view重绘时,用的依 ...
- [转]什么是C++虚函数、虚函数的作用和使用方法
我们知道,在同一类中是不能定义两个名字相同.参数个数和类型都相同的函数的,否则就是“重复定义”.但是在类的继承层次结构中,在不同的层次中可以出现名字相同.参数个数和类型都相同而功能不同的函数.例如在例 ...
- es5 温故而知新 创建私有成员、私有变量、特权变量的方法
其实js是不支持私有变量的.哪怕到es6的class语法.虽然有许多变相的方式.但非常冗余而不推崇. 这里介绍的实际上也不是class语法,而是普通的函数,并且利用IIFE(闭包)的方式来实现私有. ...
- Linux 命令 统计进程数目
ps -efL | grep python | wc -l 此命令的意思是查看 Python的进程数目 ps -ef|grep python|grep -v grep|cut -c -|xargs k ...