emo场景,以oracle自带库中的表emp为例:

select ename,deptno from emp order by deptno;

ENAME DEPTNO
CLARK 10
KING 10
MILLER 10
SMITH 20
ADAMS 20
FORD 20
SCOTT 20
JONES 20
ALLEN 30
BLAKE 30
MARTIN 30
JAMES 30
TURNER 30
WARD 30

现在想要将同一部门的人给合并成一行记录,如何做呢?如下:

ENAME DEPTNO
CLARK,KING,MILLER 10
ADAMS,FORD,JONES,SCOTT,SMITH 20
ALLEN,BLAKE,JAMES,MARTIN,TURNER,WARD 30

通常我们都是自己写函数或在程序中处理,这里我们利用oracle自带的分析函数row_number()和sys_connect_by_path来进行sql语句层面的多行到单行的合并,并且效率会非常高。

基本思路:

1、对deptno进行row_number()按ename排位并打上排位号

select deptno,ename,row_number() over(partition by deptno order by deptno,ename) rank
from emp order by deptno,ename;

DEPTNO ENAME RANK
10 CLARK 1
10 KING 2
10 MILLER 3
20 ADAMS 1
20 FORD 2
20 JONES 3
20 SCOTT 4
20 SMITH 5
30 ALLEN 1
30 BLAKE 2
30 JAMES 3
30 MARTIN 4
30 TURNER 5
30 WARD 6

可看出,经过row_number()后,部门人已经按部门和人名进行了排序,并打上了一个位置字段rank

2、利用oracle的递归查询connect by进行表内递归,并通过sys_connect_by_path进行父子数据追溯串的构造,这里要针对ename字段进行构造,使之合并在一个字段内(数据很多,只截取部分)

select deptno,ename,rank,level as curr_level,
ltrim(sys_connect_by_path(ename,','),',') ename_path from (
select deptno,ename,row_number() over(partition by deptno order by deptno,ename) rank
from emp order by deptno,ename) connect by deptno = prior deptno and rank-1 = prior rank;

各部门递归后的数据量都是:(1+n)/2 * n 即:deptno=10 数据量:(1+3)/2 * 3 = 6;

deptno=20 数据量:(1+5)/2 * 5 = 15;      deptno=30 数据量:(1+6)/2 * 6 = 21;

DEPTNO ENAME RANK CURR_LEVEL ENAME_PATH
10 CLARK 1 1 CLARK
10 KING 2 2 CLARK,KING
10 MILLER 3 3 CLARK,KING,MILLER
10 KING 2 1 KING
10 MILLER 3 2 KING,MILLER
10 MILLER 3 1 MILLER
DEPTNO ENAME RANK CURR_LEVEL ENAME_PATH
20 ADAMS 1 1 ADAMS
20 FORD 2 2 ADAMS,FORD
20 JONES 3 3 ADAMS,FORD,JONES
20 SCOTT 4 4 ADAMS,FORD,JONES,SCOTT
20 SMITH 5 5 ADAMS,FORD,JONES,SCOTT,SMITH
20 FORD 2 1 FORD
20 JONES 3 2 FORD,JONES
20 SCOTT 4 3 FORD,JONES,SCOTT
20 SMITH 5 4 FORD,JONES,SCOTT,SMITH
20 JONES 3 1 JONES
20 SCOTT 4 2 JONES,SCOTT
20 SMITH 5 3 JONES,SCOTT,SMITH
20 SCOTT 4 1 SCOTT
20 SMITH 5 2 SCOTT,SMITH
20 SMITH 5 1 SMITH

这里我们仅列出deptno=10、20的,至此我们应该能否发现一些线索了,即每个部门中,curr_level最高的那行,有我们所需要的数据。那后面该怎么办,取出那个数据? 对了,继续用row_number()进行排位标记,然后再按排位标记取出即可。

3、 对deptno继续进行row_number()按curr_level排位

select deptno,ename_path,row_number() over(partition by deptno order by deptno,curr_level desc) ename_path_rank from (select deptno,ename,rank,level as curr_level,
ltrim(sys_connect_by_path(ename,','),',') ename_path from (
select deptno,ename,row_number() over(partition by deptno order by deptno,ename) rank
from emp order by deptno,ename) connect by deptno = prior deptno and rank-1 = prior rank);

DEPTNO ENAME_PATH ENAME_PATH_RANK
10 CLARK,KING,MILLER 1
10 CLARK,KING 2
10 KING,MILLER 3
10 CLARK 4
10 KING 5
10 MILLER 6
DEPTNO ENAME_PATH ENAME_PATH_RANK
20 ADAMS,FORD,JONES,SCOTT,SMITH 1
20 ADAMS,FORD,JONES,SCOTT 2
20 FORD,JONES,SCOTT,SMITH 3
20 ADAMS,FORD,JONES 4
20 FORD,JONES,SCOTT 5
20 JONES,SCOTT,SMITH 6
20 ADAMS,FORD 7
20 FORD,JONES 8
20 SCOTT,SMITH 9
20 JONES,SCOTT 10
20 ADAMS 11
20 JONES 12
20 SMITH 13
20 SCOTT 14
20 FORD 15

这里还是仅列出deptno为10、20的,至此应该很明了了,在进行一次查询,取ename_path_rank为1的即可获得我们想要的结果。

4、获取想要排位的数据,即得部门下所有人多行到单行的合并

select deptno,ename_path from (select deptno,ename_path,
row_number() over(partition by deptno order by deptno,curr_level desc) ename_path_rank
from (select deptno,ename,rank,level as curr_level,
ltrim(sys_connect_by_path(ename,','),',') ename_path from (
select deptno,ename,row_number() over(partition by deptno order by deptno,ename) rank
from emp order by deptno,ename) connect by deptno = prior deptno and rank-1 = prior rank))
where ename_path_rank=1;

利用Oracle分析函数row_number和sys_connect_by_path实现多行数据合并为一行的更多相关文章

  1. Oracle查询多行数据合并成一行数据

    例如: select base_id, translate (ltrim (text1, '/'), '*/', '*,') xmmc,translate (ltrim (text2, '/'), ' ...

  2. 数据库groub by分组后,把多行数据合并成一行数据(Oracle、Postgres)

    关键字 row_number() over (partition by)   例如,下面的数据, 这是按照name分组后,展示property值. 我们想得到这样的值; 第一步:将每一组的proper ...

  3. oracle 聚合函数 LISTAGG ,将多行结果合并成一行

    LISTAGG( to_char(Item_Category_Name), ',') WITHIN GROUP(ORDER BY Item_Category_Name)  -- 将 Item_Cate ...

  4. oracle 多行数据合并一行数据

    在工作中遇见的oracle知识,多行合并成一行,记录一下 1.取出需要的数据,代码: (SELECT to_char(m.f_meetdate, 'yyyy-MM-dd'), decode(nvl(m ...

  5. Oracle 分析函数--Row_Number()

    row_number() over ([partition by col1] order by col2) ) as 别名 表示根据col1分组,在分组内部根据 col2排序 而这个“别名”的值就表示 ...

  6. Oracle一列的多行数据拼成一行显示字符

    Oracle一列的多行数据拼成一行显示字符   oracle 提供了两个函数WMSYS.WM_CONCAT 和 ListAgg函数.    www.2cto.com   先介绍:WMSYS.WM_CO ...

  7. 数据库多行数据合并一行(sqlserver、Oracle、Mysql)

    我们日常查询数据时,经常会有将查询到的数据按照某一列分组显示(合并多行数据),比如: 表结构: ),coursename )); 需要将以上数据按照用户名分组,所选课程列不同项之间用逗号隔开,在一行中 ...

  8. Oracle分析函数row_number()等的使用实例

    --分析函数 --rank() over(order by) --值相同,排名相同,序号跳跃 select * from t_account select rank() over(order by u ...

  9. 利用Oracle的row_number() over函数消除重复的记录

    .select d.id,d.outer_code from dict_depts_source d order by outer_code(查看重复数据) .select d.id,d.outer_ ...

随机推荐

  1. Openlayer3之绚丽的界面框架-Materialize

    一群做C++的老伙计搞前端开发,徒手写html和css应该会折寿..在网上找了半天,Materialize算是用起来很方便的一款前端界面框架.Google的Material Design看起来感觉还是 ...

  2. 开发Spring过程中几个常见异常(一)

    异常一:java.lang.NoClassDefFoundError: org/apache/commons/logging/LogFactory 原因:未导入有关日志管理的jar包或者未添加到路径. ...

  3. Android为TV端助力 SharedPreferences 轻量级存储!

    首先在当前进程也就是当前的项目里面进行存储 SharedPreferences.Editor editor = mContext.getSharedPreferences("tvplay&q ...

  4. (后端)swagger

    Swagger 文档提供了一个方法,使我们可以用指定的 JSON 或者 YAML 摘要来描述你的 API,包括了比如 names.order 等 API 信息. 你可以通过一个文本编辑器来编辑 Swa ...

  5. centos7安装jdk环境

    有时候安装一些软件或者服务都需要jdk环境,今天就在centos上安装最新的jdk环境. 检测历时安装 1.查看Linux自带的JDK是否已安装 # java -version 2.查看JDK信息 # ...

  6. shell编程—简介(一)

    1.shell概念 shell是一个用C语音编写的程序,他是用户使用Linux的桥梁 shell既是一种命令语音,又是一种程序设计语音 shell是指一种应用程序,这个应用程序提供一个界面,用户通过这 ...

  7. IOS UIWebView用法

    转自猫猫小屋 IOS webview控件使用简介(一) IOS webview控件使用简介(二)–加载本地html

  8. Linux唤醒抢占----Linux进程的管理与调度(二十三)

    1. 唤醒抢占 当在try_to_wake_up/wake_up_process和wake_up_new_task中唤醒进程时, 内核使用全局check_preempt_curr看看是否进程可以抢占当 ...

  9. [Hive_10] Hive 的分析函数

    0. 说明 Hive 的分析函数 窗口函数  | 排名函数 | 最大值 | 分层次 | lead && lag 统计活跃用户 | cume_dist 1. 窗口函数(开窗函数) ove ...

  10. LeetCode算法题-Power Of Three(Java实现-七种解法)

    这是悦乐书的第204次更新,第215篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第71题(顺位题号是326).给定一个整数,写一个函数来确定它是否为3的幂.例如: 输入 ...