oracle一行变一列,oracle多行变一行
今天遇到将多行转为一行的一个操作,多谢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多行变一行相关推荐
- 如何将系统变量中的Path变量值由一整行变的条理清晰
如何将系统变量中的Path变量值由一整行变的条理清晰 问题:在配置环境变量时,发现变量值呈现一整行的状态,不好查找需要的东西,如下图 解决方法:将C:\Windows\System32放在所有变量值前 ...
- 怎么把好几行弄成一行_【excle 如何多行变一行】excel中怎么把多行同一个人的数据变成一行?...
excel中怎样实现多行数据变成一行数据 最简单的方法就是讲姓名2制(即成员)后在"本人"所,家庭成员1所在列做"选择性粘贴",然后选择"行列互换&q ...
- pandas DataFrame增加一行、一列、多行、多列
# 增加一行或者一列 import numpy as np import pandas as pd# 增加一行 df = pd.DataFrame(np.random.rand(4,5), colum ...
- oracle 调整输出的列宽、行宽
调整列宽col,调整行宽set linesize before: C:\>sqlplus "/as sysdba"SQL*Plus: Release 10.2.0.1.0 - ...
- oracle数据库将一列的值拼接成一行,并且各个值之间用逗号隔开
使用场景:把某一列值转换为逗号分隔的字符串 例子:比如查询所有的的表空间如下,现在要获得所有的表空间用逗号分隔的字符串(比如rman duplicate的时候skip表空间) SQL> sele ...
- oracle分组后伪列,Oracle伪列和伪表和分组函数(row_number,Rank)
oracle的伪列以及伪表 oracle系统为了实现完整的关系数据库功能,系统专门提供了一组成为伪列(Pseudocolumn)的数据库列,这些列不是在建立对象时由我们完成的,而是在我们建立时由Ora ...
- oracle创建时分秒列,oracle 11g 分区表创建(年月日周时分秒)
oracle 11g 支持自动分区,不过得在创建表时就设置好分区. 如果已经存在的表需要改分区表,就需要将当前表 rename后,再创建新表,然后复制数据到新表,然后删除旧表就可以了. 一.为什么要分 ...
- oracle 纵列 转 横列,oracle sql小结(主要讲横列转换的例子)decode 以及case
--建表 create table kecheng ( id NUMBER, name VARCHAR2(20), course VARCHAR2(20), score NUMBER ); --插入数 ...
- oracle设计自增列,oracle中实现自增列
oracle中实现自增列 1.创建学生表: CREATE TABLE student ( xh number primary key, Name varchar2(10) not null); 2. ...
最新文章
- 【FFmpeg】详解FFmpeg解封装、解码流程
- 摸清源头 让电脑运行不再迟缓
- php丢弃,在IIS 7.5中,PHP吓坏了(连接丢失,连接被丢弃)
- JS经典面试题03-引用类型连续赋值a.x = a = { n: 2 }
- Document Builder: 如何分析rule执行逻辑
- android交叉编译libxml2,Openwrt 交叉编译libxml2(示例代码)
- python测试报告
- perl语言中数组初始化为空和undef的不同
- 睡眠阶段分期——SVM和ELM分别与粒子群算法结合(function)
- 家谱制作软件如何下载及安装
- Redmi AirDots只有一边有声音?? 如何进行双耳连接?
- 乾隆盛世,居然是“饥饿的盛世”?
- 电脑上的PDF文件太大了怎么办?
- 视频会议,远程协助平台接入亮亮视野AR眼镜,UVC摄像头方案
- 清华大学 博士后 原来入的计算机科学与技术 现在能入软件工程吗,清华大学软件学院...
- matlab 更换坐标轴_matlab怎么调整坐标轴范围-Matlab修改坐标轴标注范围的方法 - 河东软件园...
- Docker-容器化应用
- 如何快速的删除空间黑历史说说
- 使用Feign传输File类型的数据
- (翻译)斑马纹模式(Alternating Row Colors)
热门文章
- SMARTFORM 转 PDF
- 家乐福首家付费会员店遇到「喜与忧」背后,行业同质化问题浮出水面
- 突破冰箱局限!海尔智家AWE发布美食物联生态平台
- linux汇编和x86汇编,linux平台学x86汇编(四):从“hello world!”开始
- pydroid3怎么保存_pydroid3
- python画决策树如何避免太多内容重叠在一起_Python手写决策树并应对过度拟合问题...
- gophp解释器_对比平台--Go和PHP之间的区别
- python进制转换函数汇总-攻防世界-Misc-掀桌子;
- Python字符串前加f、r、b、u的不同用法
- python 中 property 属性的讲解及应用