demo场景,以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;
代码
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 empno,
deptno,
ename,
rank,
level as curr_level,
ltrim(sys_connect_by_path(ename, ','), ',') ename_path
from (select deptno,
ename,
empno,
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;
—————————————————————————————————————————————————
查询表中的一个字段,返回了多行,就把这么多行的数据都拼成一个字符串。
例: id name
1 aa
2 bb
3 cc
要的结果是"aa,bb,cc"
select WMSYS.WM_CONCAT(a.name) from user a
这样的话,查询出的结果:"aa.bb.cc"
中间用点间隔,如果想替换为其他符号,例如用逗分号
select replace(WMSYS.WM_CONCAT(a.name),',',';') from user a
结果:"aa;bb;cc"
分享到:
相关推荐
### Oracle多行合并为一行的方法 在Oracle数据库中,有时候我们需要将多行数据合并成一行进行展示或处理,尤其是在报表生成、数据展示等场景中。本文将详细介绍如何使用Oracle纯SQL语句实现这一功能,并通过具体...
总结来说,通过巧妙地运用Oracle的`CONNECT BY`和`SYS_CONNECT_BY_PATH`函数,我们可以实现多行数据到一行的合并,这对于报告展示和数据分析非常实用。不过要注意的是,这种方法在大数据量下可能会有性能问题,因为...
### Oracle 10g与9i中的多行合并为一行函数详解 在Oracle数据库系统中,经常需要将多个行的数据合并成单行显示,尤其是在处理报告或者需要将多个值组合成一个字符串的情况下。本文将详细介绍如何在Oracle 10g与9i...
SQL语句用with将列分割成多列存为临时表,再将多行某个字段拼接合并为一行
在Oracle数据库中,多行记录的合并通常是为了将相同字段的多行数据整合成一行,以便于数据分析或者简化展示。这种操作在报表制作、数据整理等场景中非常常见。本篇文章将详细介绍Oracle中实现多行记录合并的几种方法...
本文实例讲述了oracle实现多行合并的方法。分享给大家供大家参考。具体分析如下: 在写sql时,经常会有将某列的字段合并起来,比如将某人名下每个月的工资列示,但是每个人只能占一行。 像这种场景,可能用行列转换...
根据提供的信息,本文将详细介绍如何在Oracle数据库中将某个字段的多行记录转换为一行记录的方法。这种方法在处理大量数据时非常有用,特别是在需要将多个值汇总到一个字段中的场景下。 ### 标题理解:“oracle某个...
这个问题涉及到字符串的连接和聚合,使得多个记录的某个字段值能够整合到一行。在Oracle中,虽然没有内置的聚合函数直接支持这种操作,但可以通过一些技巧和自定义方法来实现。下面我们将对几种常用的方法进行详细...
在Oracle数据库中,有时我们需要将多个字段值转换为单个字符串,或者将多行记录合并成一行,这在数据处理和报告生成时尤其常见。Oracle提供了多种方法来实现这一目标,包括使用内置函数、PL/SQL过程以及一些高级特性...
在Oracle数据库中,将逗号分隔的字符串转换为多行是常见的数据处理需求,尤其在需要对每个分隔项进行单独操作时。这个过程通常涉及到字符串处理函数,如`REGEXP_SUBSTR`和`REPLACE`,以及层次查询结构`CONNECT BY`。...
首先明确“合并多行字符串”的含义:即将多行记录中的某个字段的值汇总到一行中形成一个由特定分隔符连接起来的新字符串。比如,在示例数据中,我们希望将同一个国家的不同城市名称合并成一个字符串。 #### 方法一...
在Oracle的PL/SQL编程中,函数是极其重要的组成部分,它们用于处理和操作数据。本篇文章将详细讲解PL/SQL中的单行函数和组函数。 首先,单行函数是针对单行数据进行操作的函数,它们可以应用于SQL查询的不同部分,...
在SQL中,有时我们需要将具有相同属性的重复行数据合并成一行,并使用特定的分隔符,如逗号,来区分各个值。这种操作在处理报告或者数据分析时非常常见,可以减少数据的冗余,使结果更加简洁。本文将详细讲解如何在...
在Oracle数据库中,有时我们需要将同一表中多个列的值合并为一个字符串,这被称为列合并。Oracle提供了多种方法来实现这一功能,特别是在不同版本中,这些方法有所不同。以下是Oracle列合并的一些常用方法: 1. **...
要将` Reason`列的多行数据合并为一行,我们可以使用SQL函数。在这个例子中,创建了一个名为`test`的自定义函数,该函数接受`standards`作为参数,然后返回与该`standards`相关的所有`Reason`值,合并成一个字符串。...
Oracle 中实现行转列功能,并使用逗号进行隔开拼接,成为一条数据是指将多行数据合并成一行数据,并用逗号分隔每个字段的值。这种功能在实际应用中非常有用,例如在报表生成、数据分析和数据整合等场景中。 在 ...
这在你需要将一组相关的列合并为一个或多个行时非常有用。基本语法如下: ```sql SELECT column1, unpivot_column, value FROM table UNPIVOT ( value FOR unpivot_column IN (column2, column3, ...) ); ``` 在...
6. **Wm_concat函数**:`wm_concat`是Oracle的一个非标准函数,用于将多行合并为单行,类似于`listagg`。然而,由于安全性问题,从Oracle 12c开始,`wm_concat`已被弃用,建议使用`listagg`替代。 了解并熟练掌握...