oracle 转置实现
下面是3种方法
方法1:SYS_CONNECT_BY_PATH , ROW_NUMBER() OVER(PARTITION BY .. ORDER BY ..) , START WITH , CONNECT BY PRIOR 组合使用
方法2:wmsys.wm_concat
方法3:listagg(oracle 11g release 2) 用法就像聚合函数一样,通过Group by语句,把每个Group的一个字段,拼接起来.
listagg 语法概述
listagg函数的语法结构如下:
LISTAGG( [,]) WITHIN GROUP (ORDER BY ) [OVER (PARTITION BY )]
listagg虽然是聚合函数,但可以提供分析功能(比如可选的OVER()子句)。使用listagg中,下列中的元素是必须的:
- 需要聚合的列或者表达式
- WITH GROUP 关键词
- 分组中的ORDER BY子句
下面将演示listagg函数使用的例子
例:
table1 中 1个col1对应多个col2,下面我们需要把col2转置如col2字段值为
2
3
4
需要变为 2-3-4 这样的格式,并且col2值是不可枚举的有上千或上万种,这样其他有些通过decode方式的转置就不能实现
使用方法1
SELECT TT.col1,
'-' || ':' ||
TO_CHAR(SUBSTR(MAX(SYS_CONNECT_BY_PATH(TT.col2, '-')), 2)) M
--这里是为了截取掉 SYS_CONNECT_BY_PATH 在第一个值前加的"-"
FROM (SELECT T.col1,
T.col2,
T.col1 + ROW_NUMBER() OVER(PARTITION BY T.col1 ORDER BY T.col2) RN,
ROW_NUMBER() OVER(PARTITION BY T.col1 ORDER BY T.col2) RM
--上面2行用了2次 ROW_NUMBER() 是因为 col1是累加的值所以一个 T.col1 + ROW_NUMBER() 是为了区别不同的分组,ROW_NUMBER() 这个是为了设置递归的起始值,但对于不同的分组都会有这个值"1"所以需要使用2个
FROM table1 T
WHERE /*T.col1 = TO_NUMBER('1013010875782363')*/) TT --注释的部分是我测试用的
START WITH RM = 1
CONNECT BY PRIOR RN + 1 = RN
GROUP BY TT.col1 ;
方法2
select substr(tt.co, 1, length(tt.co) - 1), --去结尾"-"
tt.col1
from (select t.col1, replace(wmsys.wm_concat(t.col2 || '-'), ',', null) co --去掉","
from table1 t
--WHERE T.col1 = TO_NUMBER('1013010875782363')
group by t.col1) tt;
方法3
select population,
nation,
city,
listagg(city,',') within GROUP (order by city) over (partition by nation) rank
from temp
或者
select nation,listagg(city,',') within GROUP (order by city)
from temp
group by nation
第二个虽然简单但是
wmsys.wm_concat对象实现行列转换的方法,这种方法不被Oracle所推荐,因为WMSYS用户用于Workspace Manager,其函数对象可能因版本而不同,这种变化在11.2.0.3及10.2.0.5中体现出来。原本WM_CONCAT函数返回值为VARCHAR2变更为CLOB。这一变化导致了很多程序的异常。
参考
http://www.eygle.com/archives/2012/10/wmsys_wm_concat.html
-------20150522 update--------
转置实现
说明:把 TF_B_TRADE_SP 里一个订单的SP增加或减少的 SP_PRODUCT_ID 转置后以一条行记录的形式列出
SELECT TT.TRADE_ID,
'-' || ',' ||
SUBSTR(MAX(SYS_CONNECT_BY_PATH(TT.SP_PRODUCT_ID, '-')), 2)
FROM (SELECT T.TRADE_ID,
T.SP_PRODUCT_ID,
T.MODIFY_TAG,
T.TRADE_ID + ROW_NUMBER() OVER(PARTITION BY T.TRADE_ID ORDER BY T.SP_PRODUCT_ID) RN,
ROW_NUMBER() OVER(PARTITION BY T.TRADE_ID ORDER BY T.SP_PRODUCT_ID) RM
FROM TF_B_TRADE_SP T
WHERE T.TRADE_ID = TO_NUMBER(:VTRADE_ID)
AND T.MODIFY_TAG IN ('', 'B')) TT
START WITH RM = 1
CONNECT BY PRIOR RN + 1 = RN
GROUP BY TT.TRADE_ID
UNION ALL
SELECT TT.TRADE_ID,
'+' || ',' ||
SUBSTR(MAX(SYS_CONNECT_BY_PATH(TT.SP_PRODUCT_ID, '-')), 2)
FROM (SELECT T.TRADE_ID,
T.SP_PRODUCT_ID,
T.MODIFY_TAG,
T.TRADE_ID + ROW_NUMBER() OVER(PARTITION BY T.TRADE_ID ORDER BY T.SP_PRODUCT_ID) RN,
ROW_NUMBER() OVER(PARTITION BY T.TRADE_ID ORDER BY T.SP_PRODUCT_ID) RM
FROM TF_B_TRADE_SP T
WHERE T.TRADE_ID = TO_NUMBER(:VTRADE_ID)
AND T.MODIFY_TAG IN ('', 'A')) TT
START WITH RM = 1
CONNECT BY PRIOR RN + 1 = RN
GROUP BY TT.TRADE_ID;
修改后最后写好是这样
SELECT MI.M || ',' || AD.A
FROM (SELECT TT.TRADE_ID,
'-' || ':' ||
TO_CHAR(SUBSTR(MAX(SYS_CONNECT_BY_PATH(TT.SP_PRODUCT_ID, '_')),
2)) M
FROM (SELECT T.TRADE_ID,
T.SP_PRODUCT_ID,
T.MODIFY_TAG,
T.TRADE_ID + ROW_NUMBER() OVER(PARTITION BY T.TRADE_ID ORDER BY T.SP_PRODUCT_ID) RN,
ROW_NUMBER() OVER(PARTITION BY T.TRADE_ID ORDER BY T.SP_PRODUCT_ID) RM
FROM TF_B_TRADE_SP T
WHERE T.TRADE_ID = TO_NUMBER('')
AND T.MODIFY_TAG IN ('', 'B')) TT
START WITH RM = 1
CONNECT BY PRIOR RN + 1 = RN
GROUP BY TT.TRADE_ID) MI,
(SELECT TT.TRADE_ID,
'+' || ':' ||
TO_CHAR(SUBSTR(MAX(SYS_CONNECT_BY_PATH(TT.SP_PRODUCT_ID, '_')),
2)) A
FROM (SELECT T.TRADE_ID,
T.SP_PRODUCT_ID,
T.MODIFY_TAG,
T.TRADE_ID + ROW_NUMBER() OVER(PARTITION BY T.TRADE_ID ORDER BY T.SP_PRODUCT_ID) RN,
ROW_NUMBER() OVER(PARTITION BY T.TRADE_ID ORDER BY T.SP_PRODUCT_ID) RM
FROM TF_B_TRADE_SP T
WHERE T.TRADE_ID = TO_NUMBER('')
AND T.MODIFY_TAG IN ('', 'A')) TT
START WITH RM = 1
CONNECT BY PRIOR RN + 1 = RN
GROUP BY TT.TRADE_ID) AD;
说明
SELECT TT.col1,
'-' || ':' ||
TO_CHAR(SUBSTR(MAX(SYS_CONNECT_BY_PATH(TT.col2, '-')), 2)) M
--这里是为了截取掉 SYS_CONNECT_BY_PATH 在第一个值前加的"-"
FROM (SELECT T.col1,
T.col2,
T.col1 + ROW_NUMBER() OVER(PARTITION BY T.col1 ORDER BY T.col2) RN,
ROW_NUMBER() OVER(PARTITION BY T.col1 ORDER BY T.col2) RM
--上面2行用了2次 ROW_NUMBER() 是因为 col1是累加的值所以一个 T.col1 + ROW_NUMBER() 是为了区别不同的分组,ROW_NUMBER() 这个是为了设置递归的起始值,但对于不同的分组都会有这个值"1"所以需要使用2个
FROM table1 T
WHERE /*T.col1 = TO_NUMBER('1013010875782363')*/) TT --注释的部分是我测试用的
START WITH RM = 1
CONNECT BY PRIOR RN + 1 = RN
GROUP BY TT.col1 ;
oracle 转置实现的更多相关文章
- 行列转置(Oracle)
一.Oracle行列转置 1.行转列 (1)创建表格.插入测试数据 create table student( id number, name ), course ), score number ) ...
- [转]Oracle SQL函数pivot、unpivot转置函数实现行转列、列转行
原文地址:http://blog.csdn.net/seandba/article/details/72730657 函数PIVOT.UNPIVOT转置函数实现行转列.列转行,效果如下图所示: 1.P ...
- Oracle 行列转置
两种简单的行列转置 1.固定列数的行列转换如student subject grade--------- ---------- --------student1 语文 80st ...
- 表的转置 行转列: DECODE(Oracle) 和 CASE WHEN 的异同点
异同点 都可以对表行转列: DECODE功能上和简单Case函数比较类似,不能像Case搜索函数一样,进行更复杂的判断 在Case函数中,可以使用BETWEEN, LIKE, IS NULL, IN, ...
- ORACLE的sign函数和DECODE函数
比较大小函数 sign 函数语法:sign(n) 函数说明:取数字n的符号,大于0返回1,小于0返回-1,等于0返回0 示例:一.select sign( 100 ),sign(- 100 ),sig ...
- Oracle DECODE函数的语法介绍
Oracle DECODE函数功能很强,下面就为您详细介绍Oracle DECODE函数的用法,希望可以让您对Oracle DECODE函数有更多的了解. Oracle DECODE函数 Oracle ...
- ORACLE 字符串操作
1 字符串连接 SQL> select 'abc' || 'def' from dual; 'ABC'|------abcdef 2 小写SQL>select lower('ABC01 ...
- Oracle字符串操作[转:http://www.cnblogs.com/xd502djj/archive/2010/08/11/1797577.html]
ORACLE 字符串操作 1 字符串连接 SQL> select 'abc' || 'def' from dual; 'ABC'|------abcdef 2 小写SQL>select ...
- Oracle Sql优化之报表和数据仓库运算
1.行转列:有两种写法,一种是case when end写法,另一种写法是pivot(oracle 11g新增) select job, then sal end) as sal10, then sa ...
随机推荐
- Yii Framework隐藏index.php文件的步骤
Yii Framework隐藏index.php文件的步骤 作者:feebas 发布于:2012-4-23 13:36 Monday 分类:Yii Framework 1.开启apache的mod_r ...
- sparksql进阶
scala> val df=spark.read.json("/tmp/pdf1json")df: org.apache.spark.sql.DataFrame = [age ...
- 利用STM32CubeMX生成HID双向通讯工程
使用开发板为正点原子ministm32 现在我们先使用HID descriptor Tool来生成我们需要的hid的 保存使用选择.H // D:\usb资料\HID\MSDEV\Projects\t ...
- 完美解决ubuntu下sublime中文输入问题
声明 1.本人整理文章,转载请注明出处. 2.参考资料 http://my.oschina.net/tsl0922/blog/113495 问题描述 在ubuntu下想使用sublime,但是不能输入 ...
- SVM视频跟踪
# -*- coding: utf-8 -*- """ Created on Thu Nov 8 21:44:12 2018 @author: xg "&quo ...
- DevExpress控件TExtLookupComboBox实现多列模糊匹配输入的方法
本方案不需要修改控件源码,是完美解决支持多列模糊匹配快速输入的最佳方案!! 1.把列的Properties属性设置为ExtLookupComboBox. Properties.Incrementa ...
- Delphi访问网页中的下拉菜单
Delphi通过TWebBrowser浏览网页,然后访问该网页中的下拉菜单: uses MsHtml;procedure TForm1.Button1Click(Sender: TObject);va ...
- Dictionary,hashtable, stl:map有什么异同?
相同点:字典和map都是泛型,而hashtable不是泛型. 不同点:三者算法都不相同 Hashtable,看名字能想到,它是采用传统的哈希算法:探测散列算法,而字典则采用的是散列拉链算法,效率较高, ...
- node-sass:npm install node-sass --save
从git上拉下来的项目,要先安装依赖, 再运行. 缺少node-sass:npm install node-sass --save
- Linux下MySQL5.7.18二进制包安装(手动添加配置文件my_default.cnf)
本文出处:http://www.cnblogs.com/wy123/p/6815049.html 最新在学习MySQL,纯新手,对Linux了解的也不多,因为是下载的最新版的MySQL(MySQL5. ...