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. 2018-05-14 代码考古-Python3官方教程字典例程

    知乎原链 Data Structures中的第一个例程: >>> tel = {'jack': 4098, 'sape': 4139} >>> tel['guido ...

  2. jQuery计算文本宽度和input标签根据输入字符动态自适应宽度的实现

    jQuery计算文本宽度的原理是利用html提供的<pre>标签,向dom中动态添加<pre>标签,标签里的内容就是要测试长度的文本,获取完长度之后再删除刚才添加的<pr ...

  3. openlayers3 实现测距 面积

    <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <m ...

  4. mybatis的三种批量插入以及次效率比较

    1.表结构 CREATE TABLE `t_user` ( `id` varchar(32) CHARACTER SET utf8 NOT NULL COMMENT '主键', `name` varc ...

  5. python 标准类库-并行执行之subprocess-子进程管理

    标准类库-并行执行之subprocess-子进程管理 by:授客QQ:1033553122 1.使用subprocess模块 以下函数是调用子进程的推荐方法,所有使用场景它们都能处理.也可用Popen ...

  6. 关于相机拍照获取图片onActivityResult返回data 为null的问题

    调用相机拍摄方法 /** * capture new image */ protected void selectPicFromCamera() { if (!EaseCommonUtils.isSd ...

  7. 结对编程--四则运算(Java)萧英杰 夏浚杰

    结对编程--四则运算(Java)萧英杰 夏浚杰 Github项目地址 功能要求 题目:实现一个自动生成小学四则运算题目的命令行程序 使用 -n 参数控制生成题目的个数(实现) 使用 -r 参数控制题目 ...

  8. 排序算法----冒泡排序java(写得绝对比其他博文易懂明了实用)

    本来不想写的,看到别人写的都不符合自己心意 需进行n(n-1)/2次比较和记录移动,时间复杂度为O(n*n) import java.util.Arrays; import java.util.Sca ...

  9. OpenCvSharp尝试

    OpenCvSharp是封装了OpenCV的.net版本 项目地址:https://github.com/shimat/opencvsharp 简单使用: 1.NuGet安装 2.使用OpenCvSh ...

  10. VMware 15 pro虚拟机

    VMware虚拟机都到VMware Workstation 15 Pro,真快,VMware 14还没用好