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 这样的格式,并且col2值是不可枚举的有上千或上万种,这样其他有些通过decode方式的转置就不能实现

使用方法1

 1 SELECT TT.col1,
 2        ‘-‘ || ‘:‘ ||
 3        TO_CHAR(SUBSTR(MAX(SYS_CONNECT_BY_PATH(TT.col2, ‘-‘)), 2)) M
 4        --这里是为了截取掉 SYS_CONNECT_BY_PATH 在第一个值前加的"-"
 5   FROM (SELECT T.col1,
 6                T.col2,
 7                T.col1 + ROW_NUMBER() OVER(PARTITION BY T.col1 ORDER BY T.col2) RN,
 8                ROW_NUMBER() OVER(PARTITION BY T.col1 ORDER BY T.col2) RM
 9         --上面2行用了2次 ROW_NUMBER() 是因为 col1是累加的值所以一个 T.col1 + ROW_NUMBER() 是为了区别不同的分组,ROW_NUMBER() 这个是为了设置递归的起始值,但对于不同的分组都会有这个值"1"所以需要使用2个
10           FROM table1 T
11          WHERE /*T.col1 = TO_NUMBER(‘1013010875782363‘)*/) TT  --注释的部分是我测试用的
12  START WITH RM = 1
13 CONNECT BY PRIOR RN + 1 = RN
14  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 转置后以一条行记录的形式列出

 1 SELECT TT.TRADE_ID,
 2        ‘-‘ || ‘,‘ ||
 3        SUBSTR(MAX(SYS_CONNECT_BY_PATH(TT.SP_PRODUCT_ID, ‘-‘)), 2)
 4   FROM (SELECT T.TRADE_ID,
 5                T.SP_PRODUCT_ID,
 6                T.MODIFY_TAG,
 7                T.TRADE_ID + ROW_NUMBER() OVER(PARTITION BY T.TRADE_ID ORDER BY T.SP_PRODUCT_ID) RN,
 8                ROW_NUMBER() OVER(PARTITION BY T.TRADE_ID ORDER BY T.SP_PRODUCT_ID) RM
 9           FROM TF_B_TRADE_SP T
10          WHERE T.TRADE_ID = TO_NUMBER(:VTRADE_ID)
11            AND T.MODIFY_TAG IN (‘1‘, ‘B‘)) TT
12  START WITH RM = 1
13 CONNECT BY PRIOR RN + 1 = RN
14  GROUP BY TT.TRADE_ID
15 UNION ALL
16 SELECT TT.TRADE_ID,
17        ‘+‘ || ‘,‘ ||
18        SUBSTR(MAX(SYS_CONNECT_BY_PATH(TT.SP_PRODUCT_ID, ‘-‘)), 2)
19   FROM (SELECT T.TRADE_ID,
20                T.SP_PRODUCT_ID,
21                T.MODIFY_TAG,
22                T.TRADE_ID + ROW_NUMBER() OVER(PARTITION BY T.TRADE_ID ORDER BY T.SP_PRODUCT_ID) RN,
23                ROW_NUMBER() OVER(PARTITION BY T.TRADE_ID ORDER BY T.SP_PRODUCT_ID) RM
24           FROM TF_B_TRADE_SP T
25          WHERE T.TRADE_ID = TO_NUMBER(:VTRADE_ID)
26            AND T.MODIFY_TAG IN (‘0‘, ‘A‘)) TT
27  START WITH RM = 1
28 CONNECT BY PRIOR RN + 1 = RN
29  GROUP BY TT.TRADE_ID;

修改后最后写好是这样

 1 SELECT MI.M || ‘,‘ || AD.A
 2   FROM (SELECT TT.TRADE_ID,
 3                ‘-‘ || ‘:‘ ||
 4                TO_CHAR(SUBSTR(MAX(SYS_CONNECT_BY_PATH(TT.SP_PRODUCT_ID, ‘_‘)),
 5                               2)) M
 6           FROM (SELECT T.TRADE_ID,
 7                        T.SP_PRODUCT_ID,
 8                        T.MODIFY_TAG,
 9                        T.TRADE_ID + ROW_NUMBER() OVER(PARTITION BY T.TRADE_ID ORDER BY T.SP_PRODUCT_ID) RN,
10                        ROW_NUMBER() OVER(PARTITION BY T.TRADE_ID ORDER BY T.SP_PRODUCT_ID) RM
11                   FROM TF_B_TRADE_SP T
12                  WHERE T.TRADE_ID = TO_NUMBER(‘1013010875782363‘)
13                    AND T.MODIFY_TAG IN (‘1‘, ‘B‘)) TT
14          START WITH RM = 1
15         CONNECT BY PRIOR RN + 1 = RN
16          GROUP BY TT.TRADE_ID) MI,
17        (SELECT TT.TRADE_ID,
18                ‘+‘ || ‘:‘ ||
19                TO_CHAR(SUBSTR(MAX(SYS_CONNECT_BY_PATH(TT.SP_PRODUCT_ID, ‘_‘)),
20                               2)) A
21           FROM (SELECT T.TRADE_ID,
22                        T.SP_PRODUCT_ID,
23                        T.MODIFY_TAG,
24                        T.TRADE_ID + ROW_NUMBER() OVER(PARTITION BY T.TRADE_ID ORDER BY T.SP_PRODUCT_ID) RN,
25                        ROW_NUMBER() OVER(PARTITION BY T.TRADE_ID ORDER BY T.SP_PRODUCT_ID) RM
26                   FROM TF_B_TRADE_SP T
27                  WHERE T.TRADE_ID = TO_NUMBER(‘1013010875782363‘)
28                    AND T.MODIFY_TAG IN (‘0‘, ‘A‘)) TT
29          START WITH RM = 1
30         CONNECT BY PRIOR RN + 1 = RN
31          GROUP BY TT.TRADE_ID) AD;

说明

 1 SELECT TT.col1,
 2        ‘-‘ || ‘:‘ ||
 3        TO_CHAR(SUBSTR(MAX(SYS_CONNECT_BY_PATH(TT.col2, ‘-‘)), 2)) M
 4        --这里是为了截取掉 SYS_CONNECT_BY_PATH 在第一个值前加的"-"
 5   FROM (SELECT T.col1,
 6                T.col2,
 7                T.col1 + ROW_NUMBER() OVER(PARTITION BY T.col1 ORDER BY T.col2) RN,
 8                ROW_NUMBER() OVER(PARTITION BY T.col1 ORDER BY T.col2) RM
 9         --上面2行用了2次 ROW_NUMBER() 是因为 col1是累加的值所以一个 T.col1 + ROW_NUMBER() 是为了区别不同的分组,ROW_NUMBER() 这个是为了设置递归的起始值,但对于不同的分组都会有这个值"1"所以需要使用2个
10           FROM table1 T
11          WHERE /*T.col1 = TO_NUMBER(‘1013010875782363‘)*/) TT  --注释的部分是我测试用的
12  START WITH RM = 1
13 CONNECT BY PRIOR RN + 1 = RN
14  GROUP BY TT.col1 ;

时间: 2024-08-05 05:05:05

oracle 转置实现的相关文章

Oracle使用SQL实现矩阵转置

在使用数据库使用报表时,往往会遇到矩阵转置.这个需求在Excel是很容易实现的,但很多人都不知道怎么用Oracle数据库实现,下面给大家展示几种使用SQL实现的方法. 需求:表1转置成表2 测试数据: CREATE TABLE TMP AS SELECT 'A1' AS A, 'B1' AS B FROM DUAL UNION ALL SELECT 'A2' AS A, 'B2' AS B FROM DUAL UNION ALL SELECT 'A3' AS A, 'B3' AS B FROM

Oracle行列转置

两种简单的行列转置 1.固定列数的行列转换如student subject grade--------- ---------- --------student1 语文 80student1 数学 70student1 英语 60student2 语文 90student2 数学 80student2 英语 100--转换为 语文 数学 英语student1 80 70 60student2 90 80 100--语句如下: 1 select student, 2 sum(decode(subje

【书评:Oracle查询优化改写】第五至十三章

[书评:Oracle查询优化改写]第五至十三章 一.1  BLOG文档结构图 一.2  前言部分 一.2.1  导读 各位技术爱好者,看完本文后,你可以掌握如下的技能,也可以学到一些其它你所不知道的知识,~O(∩_∩)O~: ① 字符串的处理 ② 常用分析函数 ③ 用sql输出九九乘法表 本文如有错误或不完善的地方请大家多多指正,ITPUB留言或QQ皆可,您的批评指正是我写作的最大动力. 一.2.2  实验环境介绍 oracle 11g 一.2.3  相关参考文章链接 前4章的链接参考相关连接:

转载-Oracle ORACLE的sign函数和DECODE函数

原文地址:http://www.cnblogs.com/BetterWF/archive/2012/06/12/2545829.html 转载以备用 比较大小函数 sign 函数语法:sign(n) 函数说明:取数字n的符号,大于0返回1,小于0返回-1,等于0返回0 示例:一.select sign( 100 ),sign(- 100 ),sign( 0 ) from dual; SIGN(100) SIGN(-100) SIGN(0) ---- ---- ---- 1 -1 0 二.a=10

oracle安装故障:完美解决xhost +报错: unable to open display “”

oracle安装 先切换到root用户,执行xhost + 然后再切换到oracle用户,执行export DISPLAY=:0.0 出现乱码执行export LANG=US_en 在这里给大家介绍下两种情况的常见问题: 一种是本地运行的命令,另一种则是远程ssh命令安装. DISPLAY科普 DISPLAY变量是用来设置将图形显示到何处.比如CENTOS,你用图形界面登录进去,DISPLAY自动设置为DISPLAY=:0.0表示显式到本地监视器,那么通过终端工具(例如:xshell)进去,运行

Sqlserver通过链接服务器访问Oracle的解决办法

转自http://blog.sina.com.cn/s/blog_614b6f210100t80r.html 一.创建sqlserver链接服务(sqlserver链接oracle)  首先sqlserver 链接oracle可以通过两个访问接口: “MSDAORA” 和“OraOLEDB.Oracle” 1.“MSDAORA”访问接口是由Microsoft OLE DB Provider for Oracle提供的,这里建议不使用此接口进行链接.通过该访问接口建立的链接服务器在进行查询orac

win7 64位系统 PB连接oracle数据库出现“oracle library oci.dll could not be loaded”问题的解决方法

今天与大家分享一个自己的学习笔记,希望能给遇到同样问题的人带来帮助. 不知道大家在win7 64位系统下用 PB连接oracle数据库时,是否遇到过“oracle library oci.dll could not be loaded”问题. 今天,在win7 64位系统下用 PB连接oracle数据库时,一直出现上述错误,在百度上找了很久,都没有找到一个完整的解决方案,咨询了很多人,(他们都说是我的PB和oracle没装好,但我装的时候没出现任何问题,一切都很顺利,而且PB和oracle都能正

Oracle 10g通过创建物化视图实现不同数据库间表级别的数据同步

摘自:http://blog.csdn.net/javaee_sunny/article/details/53439980 目录(?)[-] Oracle 10g 物化视图语法如下 实例演示 主要步骤 在A节点创建原表和物化视图日志 在B节点创建连接A节点的远程链接 在B节点处创建目标表和与目标表名称相同的物化视图 在B节点处刷新物化视图 升级采用存储过程定时任务JOB方式定时刷新物化视图 进一步优化 文章更新记录 参考文章 Oracle 10g 物化视图语法如下: create materia

Oracle静默安装

测试CentOS 6.5_x64下静默安装Oracle 11g R2数据库 [一.下载地址] http://www.oracle.com/technetwork/database/enterprise-edition/downloads/index.html Oracle 11g 联机文档: http://www.oracle.com/pls/db112/homepage [二.系统要求] 内存:1G(官方最低要求1G) 硬盘:40G(企业版安装所需4.29G和1.7G数据文件) 检查的命令 内