利用Oracle分析函数row_number和sys_connect_by_path实现多行数据合并为一行
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实现多行数据合并为一行的更多相关文章
- Oracle查询多行数据合并成一行数据
例如: select base_id, translate (ltrim (text1, '/'), '*/', '*,') xmmc,translate (ltrim (text2, '/'), ' ...
- 数据库groub by分组后,把多行数据合并成一行数据(Oracle、Postgres)
关键字 row_number() over (partition by) 例如,下面的数据, 这是按照name分组后,展示property值. 我们想得到这样的值; 第一步:将每一组的proper ...
- oracle 聚合函数 LISTAGG ,将多行结果合并成一行
LISTAGG( to_char(Item_Category_Name), ',') WITHIN GROUP(ORDER BY Item_Category_Name) -- 将 Item_Cate ...
- oracle 多行数据合并一行数据
在工作中遇见的oracle知识,多行合并成一行,记录一下 1.取出需要的数据,代码: (SELECT to_char(m.f_meetdate, 'yyyy-MM-dd'), decode(nvl(m ...
- Oracle 分析函数--Row_Number()
row_number() over ([partition by col1] order by col2) ) as 别名 表示根据col1分组,在分组内部根据 col2排序 而这个“别名”的值就表示 ...
- Oracle一列的多行数据拼成一行显示字符
Oracle一列的多行数据拼成一行显示字符 oracle 提供了两个函数WMSYS.WM_CONCAT 和 ListAgg函数. www.2cto.com 先介绍:WMSYS.WM_CO ...
- 数据库多行数据合并一行(sqlserver、Oracle、Mysql)
我们日常查询数据时,经常会有将查询到的数据按照某一列分组显示(合并多行数据),比如: 表结构: ),coursename )); 需要将以上数据按照用户名分组,所选课程列不同项之间用逗号隔开,在一行中 ...
- Oracle分析函数row_number()等的使用实例
--分析函数 --rank() over(order by) --值相同,排名相同,序号跳跃 select * from t_account select rank() over(order by u ...
- 利用Oracle的row_number() over函数消除重复的记录
.select d.id,d.outer_code from dict_depts_source d order by outer_code(查看重复数据) .select d.id,d.outer_ ...
随机推荐
- div 中图片溢出问题及 CSS3中图片翻转问题
如果设置一个div 装两张以上的图片,如果不设置好div的宽度和高度,就会使图片溢出. 我们知道,div是可以由图片撑开其宽高的,也就是说如果只放一张图片的情况下,不设置div的宽高,div的宽高会默 ...
- 关于python当中的@修饰符的浅析
https://blog.csdn.net/class_brick/article/details/81170697 要了解python中@装饰器的作用,首先要记住这么几点: 1. 装饰器符号 ...
- docker研究-1
Docker是一个开源的引擎,可以轻松的为任何应用创建一个轻量级的.可移植的.自给自足的容器.开发者在笔记本上编译测试通过的容器可以批量地在生产环境中部署,包括VMs(虚拟机).bare metal. ...
- input range样式优化
首先HTML代码: <input id="snrPollInterval" type="range" min="1" max=&quo ...
- Jmeter-测试计划,线程组,取样器,逻辑控制器,断言和监听器
一 测试计划: 是使用jmeter测试的起点,是其他测试元件的容器,一个完整的测试计划包括多个线程组,逻辑控制器,取样器,监听器,配置元件 用户定义的变量: 测试计划上可以添加用户定义的变量.一般添加 ...
- 智能ERP 交接班统计异常的解决方法
请注意,有交接班统计数据不准确的需开启离线统计即可解决,交接班统计是按照结账时间来进行统计的 1.点击左侧导航栏中‘更多’-进入系统设置 2.进入营业设置后-开启离线统计-点击保存
- Linux中对逻辑卷的移除
移除前先df -mT 看一下:(在上一篇的基础上:Linux中对逻辑卷进行扩容) 1.取消挂载同时删除/etc/fstab下的记录 取消挂载 umount /dev/zhi/lv-zhi 删除记录 v ...
- 2017 Pig-0.16.0安装
前提:已经装好hadoop2.7.3 单机版本: export PIG_HOME=/usr/local/pig export PATH=$PATH:$PIG_HOME/bin 运行:pig -x ...
- AspNet MVC中使用Hangfire执行定时任务
Hangfire在Aspnet中执行定时任务: 第一步: NuGet中加入Hangfire包 第二步: 添加Owin的自启动 第三步.Hangfire的后台控制仪表盘默认情况下只能本地访问,外网访问需 ...
- 【Git学习一】Git 初始化
在开始Git之旅之前,我们需要设置一下Git的配置变量. 1.告诉Git当前用户的姓名和邮件地址,配置用户名和邮件地址将在版本库提交时用到. 例子: ------------------------- ...