今天遇到将多行转为一行的一个操作,多谢oracle开发板的 wildwave 提供了比较通用的解决办法,同时也将自己搜到的这方面资料整理如下,多是用于连接列值的。

String集聚连接技术

需要将多行转换为一行,例子如下:

基础数据:

DEPTNO ENAME

---------- ----------

20 SMITH

30 ALLEN

30 WARD

20 JONES

30 MARTIN

30 BLAKE

10 CLARK

20 SCOTT

10 KING

30 TURNER

20 ADAMS

30 JAMES

20 FORD

10 MILLER

预期输出:

DEPTNO EMPLOYEES

---------- --------------------------------------------------

10 CLARK,KING,MILLER

20 SMITH,FORD,ADAMS,SCOTT,JONES

30 ALLEN,BLAKE,MARTIN,TURNER,JAMES,WARD

* LISTAGG分析函数(11g Release 2)

* WM_CONCAT内建函数

* 自定义函数

* 使用Ref Cursor实现通用函数

* 用户自定义聚集函数

* ROW_NUMBER()和SYS_CONNECT_BY_PATH函数(Oracle 9i)

* COLLECT函数(Oracle 10g)

LISTAGG分析函数(11g Release 2)

Oracle 11g Release 2介绍了LISTAGG 函数,使得聚集连接字符串变得很容易。并且允许使用我们指定连接串中的字段顺序。使用LISTAGG如下:

COLUMN employees FORMAT A50

SELECT deptno, LISTAGG(ename, ',') WITHIN GROUP (ORDER BY ename) AS employees

FROM   emp

GROUP BY deptno;

DEPTNO EMPLOYEES

---------- --------------------------------------------------

10 CLARK,KING,MILLER

20 ADAMS,FORD,JONES,SCOTT,SMITH

30 ALLEN,BLAKE,JAMES,MARTIN,TURNER,WARD

3 rows selected.

WM_CONCAT内建函数

如果你的Oracle不是11g Release 2,但是支持WM_CONCAT函数,那么解决上面的问题同样是小菜一碟,使用WM_CONCAT 函数G如下:

COLUMN employees FORMAT A50

SELECT deptno, wm_concat(ename) AS employees

FROM   emp

GROUP BY deptno;

DEPTNO EMPLOYEES

---------- --------------------------------------------------

10 CLARK,KING,MILLER

20 SMITH,FORD,ADAMS,SCOTT,JONES

30 ALLEN,BLAKE,MARTIN,TURNER,JAMES,WARD

3 rows selected.

自定义函数

另一个方法是自定义一个函数解决问题。get_employees对于给定部门返回一组员工:

CREATE OR REPLACE FUNCTION get_employees (p_deptno  in  emp.deptno%TYPE)

RETURN VARCHAR2

IS

l_text  VARCHAR2(32767) := NULL;

BEGIN

FOR cur_rec IN (SELECT ename FROM emp WHERE deptno = p_deptno) LOOP

l_text := l_text || ',' || cur_rec.ename;

END LOOP;

RETURN LTRIM(l_text, ',');

END;

/

SHOW ERRORS

COLUMN employees FORMAT A50

SELECT deptno,

get_employees(deptno) AS employees

FROM   emp

GROUP by deptno;

DEPTNO EMPLOYEES

---------- --------------------------------------------------

10 CLARK,KING,MILLER

20 SMITH,JONES,SCOTT,ADAMS,FORD

30 ALLEN,WARD,MARTIN,BLAKE,TURNER,JAMES

3 rows selected.

为了改善性能减少函数调用,我们预先过滤行数。.

COLUMN employees FORMAT A50

SELECT e.deptno,

get_employees(e.deptno) AS employees

FROM   (SELECT DISTINCT deptno

FROM   emp) e;

DEPTNO EMPLOYEES

---------- --------------------------------------------------

10 CLARK,KING,MILLER

20 SMITH,JONES,SCOTT,ADAMS,FORD

30 ALLEN,WARD,MARTIN,BLAKE,TURNER,JAMES

3 rows selected.

使用Ref Cursor实现通用函数

另一个可替代的方法是使用游标变量写一个函数来连接行值。基本和上面一样,只是传入的是一个游标,所以使得它更通用:.

CREATE OR REPLACE FUNCTION concatenate_list (p_cursor IN  SYS_REFCURSOR)

RETURN  VARCHAR2

IS

l_return  VARCHAR2(32767);

l_temp    VARCHAR2(32767);

BEGIN

LOOP

FETCH p_cursor

INTO  l_temp;

EXIT WHEN p_cursor%NOTFOUND;

l_return := l_return || ',' || l_temp;

END LOOP;

RETURN LTRIM(l_return, ',');

END;

/

SHOW ERRORS

使用如下:

COLUMN employees FORMAT A50

SELECT e1.deptno,

concatenate_list(CURSOR(SELECT e2.ename FROM emp e2 WHERE e2.deptno = e1.deptno)) employees

FROM   emp e1

GROUP BY e1.deptno;

DEPTNO EMPLOYEES

---------- --------------------------------------------------

10 CLARK,KING,MILLER

20 SMITH,JONES,SCOTT,ADAMS,FORD

30 ALLEN,WARD,MARTIN,BLAKE,TURNER,JAMES

3 rows selected.

同样的,为了减少函数调用可以预先顾虑一些行。.

COLUMN employees FORMAT A50

SELECT deptno,

concatenate_list(CURSOR(SELECT e2.ename FROM emp e2 WHERE e2.deptno = e1.deptno)) employees

FROM   (SELECT DISTINCT deptno

FROM emp) e1;

DEPTNO EMPLOYEES

---------- --------------------------------------------------

10 CLARK,KING,MILLER

20 SMITH,JONES,SCOTT,ADAMS,FORD

30 ALLEN,WARD,MARTIN,BLAKE,TURNER,JAMES

3 rows selected.

用户自定义聚集函数

如果你不想使用内置的函数,你可以自定义聚集函数:

CREATE OR REPLACE TYPE t_string_agg AS OBJECT

(

g_string  VARCHAR2(32767),

STATIC FUNCTION ODCIAggregateInitialize(sctx  IN OUT  t_string_agg)

RETURN NUMBER,

MEMBER FUNCTION ODCIAggregateIterate(self   IN OUT  t_string_agg,

value  IN      VARCHAR2 )

RETURN NUMBER,

MEMBER FUNCTION ODCIAggregateTerminate(self         IN   t_string_agg,

returnValue  OUT  VARCHAR2,

flags        IN   NUMBER)

RETURN NUMBER,

MEMBER FUNCTION ODCIAggregateMerge(self  IN OUT  t_string_agg,

ctx2  IN      t_string_agg)

RETURN NUMBER

);

/

SHOW ERRORS

CREATE OR REPLACE TYPE BODY t_string_agg IS

STATIC FUNCTION ODCIAggregateInitialize(sctx  IN OUT  t_string_agg)

RETURN NUMBER IS

BEGIN

sctx := t_string_agg(NULL);

RETURN ODCIConst.Success;

END;

MEMBER FUNCTION ODCIAggregateIterate(self   IN OUT  t_string_agg,

value  IN      VARCHAR2 )

RETURN NUMBER IS

BEGIN

SELF.g_string := self.g_string || ',' || value;

RETURN ODCIConst.Success;

END;

MEMBER FUNCTION ODCIAggregateTerminate(self         IN   t_string_agg,

returnValue  OUT  VARCHAR2,

flags        IN   NUMBER)

RETURN NUMBER IS

BEGIN

returnValue := RTRIM(LTRIM(SELF.g_string, ','), ',');

RETURN ODCIConst.Success;

END;

MEMBER FUNCTION ODCIAggregateMerge(self  IN OUT  t_string_agg,

ctx2  IN      t_string_agg)

RETURN NUMBER IS

BEGIN

SELF.g_string := SELF.g_string || ',' || ctx2.g_string;

RETURN ODCIConst.Success;

END;

END;

/

SHOW ERRORS

CREATE OR REPLACE FUNCTION string_agg (p_input VARCHAR2)

RETURN VARCHAR2

PARALLEL_ENABLE AGGREGATE USING t_string_agg;

/

SHOW ERRORS

使用如下:

COLUMN employees FORMAT A50

SELECT deptno, string_agg(ename) AS employees

FROM   emp

GROUP BY deptno;

DEPTNO EMPLOYEES

---------- --------------------------------------------------

10 CLARK,KING,MILLER

20 SMITH,FORD,ADAMS,SCOTT,JONES

30 ALLEN,BLAKE,MARTIN,TURNER,JAMES,WARD

3 rows selected.

ROW_NUMBER()和SYS_CONNECT_BY_PATH函数(Oracle 9i)

使用 ROW_NUMBER() 和SYS_CONNECT_BY_PATH 实现:

SELECT deptno,

LTRIM(MAX(SYS_CONNECT_BY_PATH(ename,','))

KEEP (DENSE_RANK LAST ORDER BY curr),',') AS employees

FROM   (SELECT deptno,

ename,

ROW_NUMBER() OVER (PARTITION BY deptno ORDER BY ename) AS curr,

ROW_NUMBER() OVER (PARTITION BY deptno ORDER BY ename) -1 AS prev

FROM   emp)

GROUP BY deptno

CONNECT BY prev = PRIOR curr AND deptno = PRIOR deptno

START WITH curr = 1;

DEPTNO EMPLOYEES

---------- --------------------------------------------------

10 CLARK,KING,MILLER

20 ADAMS,FORD,JONES,SCOTT,SMITH

30 ALLEN,BLAKE,JAMES,MARTIN,TURNER,WARD

3 rows selected.

COLLECT函数(Oracle 10g)

使用COLLECT函数,这个需要一个关联数组:

CREATE OR REPLACE TYPE t_varchar2_tab AS TABLE OF VARCHAR2(4000);

/

CREATE OR REPLACE FUNCTION tab_to_string (p_varchar2_tab  IN  t_varchar2_tab,

p_delimiter     IN  VARCHAR2 DEFAULT ',') RETURN VARCHAR2 IS

l_string     VARCHAR2(32767);

BEGIN

FOR i IN p_varchar2_tab.FIRST .. p_varchar2_tab.LAST LOOP

IF i != p_varchar2_tab.FIRST THEN

l_string := l_string || p_delimiter;

END IF;

l_string := l_string || p_varchar2_tab(i);

END LOOP;

RETURN l_string;

END tab_to_string;

/

使用如下:

COLUMN employees FORMAT A50

SELECT deptno,

tab_to_string(CAST(COLLECT(ename) AS t_varchar2_tab)) AS employees

FROM   emp

GROUP BY deptno;

DEPTNO EMPLOYEES

---------- --------------------------------------------------

10 CLARK,KING,MILLER

20 SMITH,JONES,SCOTT,ADAMS,FORD

30 ALLEN,WARD,MARTIN,BLAKE,TURNER,JAMES

3 rows selected.

oracle一行变一列,oracle多行变一行相关推荐

  1. 如何将系统变量中的Path变量值由一整行变的条理清晰

    如何将系统变量中的Path变量值由一整行变的条理清晰 问题:在配置环境变量时,发现变量值呈现一整行的状态,不好查找需要的东西,如下图 解决方法:将C:\Windows\System32放在所有变量值前 ...

  2. 怎么把好几行弄成一行_【excle 如何多行变一行】excel中怎么把多行同一个人的数据变成一行?...

    excel中怎样实现多行数据变成一行数据 最简单的方法就是讲姓名2制(即成员)后在"本人"所,家庭成员1所在列做"选择性粘贴",然后选择"行列互换&q ...

  3. pandas DataFrame增加一行、一列、多行、多列

    # 增加一行或者一列 import numpy as np import pandas as pd# 增加一行 df = pd.DataFrame(np.random.rand(4,5), colum ...

  4. oracle 调整输出的列宽、行宽

    调整列宽col,调整行宽set linesize before: C:\>sqlplus "/as sysdba"SQL*Plus: Release 10.2.0.1.0 - ...

  5. oracle数据库将一列的值拼接成一行,并且各个值之间用逗号隔开

    使用场景:把某一列值转换为逗号分隔的字符串 例子:比如查询所有的的表空间如下,现在要获得所有的表空间用逗号分隔的字符串(比如rman duplicate的时候skip表空间) SQL> sele ...

  6. oracle分组后伪列,Oracle伪列和伪表和分组函数(row_number,Rank)

    oracle的伪列以及伪表 oracle系统为了实现完整的关系数据库功能,系统专门提供了一组成为伪列(Pseudocolumn)的数据库列,这些列不是在建立对象时由我们完成的,而是在我们建立时由Ora ...

  7. oracle创建时分秒列,oracle 11g 分区表创建(年月日周时分秒)

    oracle 11g 支持自动分区,不过得在创建表时就设置好分区. 如果已经存在的表需要改分区表,就需要将当前表 rename后,再创建新表,然后复制数据到新表,然后删除旧表就可以了. 一.为什么要分 ...

  8. oracle 纵列 转 横列,oracle sql小结(主要讲横列转换的例子)decode 以及case

    --建表 create table kecheng ( id NUMBER, name VARCHAR2(20), course VARCHAR2(20), score NUMBER ); --插入数 ...

  9. oracle设计自增列,oracle中实现自增列

    oracle中实现自增列 1.创建学生表: CREATE TABLE student ( xh number primary key, Name varchar2(10) not null); 2. ...

最新文章

  1. 【FFmpeg】详解FFmpeg解封装、解码流程
  2. 摸清源头 让电脑运行不再迟缓
  3. php丢弃,在IIS 7.5中,PHP吓坏了(连接丢失,连接被丢弃)
  4. JS经典面试题03-引用类型连续赋值a.x = a = { n: 2 }
  5. Document Builder: 如何分析rule执行逻辑
  6. android交叉编译libxml2,Openwrt 交叉编译libxml2(示例代码)
  7. python测试报告
  8. perl语言中数组初始化为空和undef的不同
  9. 睡眠阶段分期——SVM和ELM分别与粒子群算法结合(function)
  10. 家谱制作软件如何下载及安装
  11. Redmi AirDots只有一边有声音?? 如何进行双耳连接?
  12. 乾隆盛世,居然是“饥饿的盛世”?
  13. 电脑上的PDF文件太大了怎么办?
  14. 视频会议,远程协助平台接入亮亮视野AR眼镜,UVC摄像头方案
  15. 清华大学 博士后 原来入的计算机科学与技术 现在能入软件工程吗,清华大学软件学院...
  16. matlab 更换坐标轴_matlab怎么调整坐标轴范围-Matlab修改坐标轴标注范围的方法 - 河东软件园...
  17. Docker-容器化应用
  18. 如何快速的删除空间黑历史说说
  19. 使用Feign传输File类型的数据
  20. (翻译)斑马纹模式(Alternating Row Colors)

热门文章

  1. SMARTFORM 转 PDF
  2. 家乐福首家付费会员店遇到「喜与忧」背后,行业同质化问题浮出水面
  3. 突破冰箱局限!海尔智家AWE发布美食物联生态平台
  4. linux汇编和x86汇编,linux平台学x86汇编(四):从“hello world!”开始
  5. pydroid3怎么保存_pydroid3
  6. python画决策树如何避免太多内容重叠在一起_Python手写决策树并应对过度拟合问题...
  7. gophp解释器_对比平台--Go和PHP之间的区别
  8. python进制转换函数汇总-攻防世界-Misc-掀桌子;
  9. Python字符串前加f、r、b、u的不同用法
  10. python 中 property 属性的讲解及应用