`
wang4674890
  • 浏览: 89368 次
  • 性别: Icon_minigender_2
  • 来自: 厦门
社区版块
存档分类
最新评论

利用Oracle分析函数实现多行数据合并为一行

 
阅读更多

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"

 

分享到:
评论

相关推荐

    sql实现多行合并一行

    总结来说,通过巧妙地运用Oracle的`CONNECT BY`和`SYS_CONNECT_BY_PATH`函数,我们可以实现多行数据到一行的合并,这对于报告展示和数据分析非常实用。不过要注意的是,这种方法在大数据量下可能会有性能问题,因为...

    Oracle多行记录合并

    在Oracle数据库中,多行记录的合并通常是为了将相同字段的多行数据整合成一行,以便于数据分析或者简化展示。这种操作在报表制作、数据整理等场景中非常常见。本篇文章将详细介绍Oracle中实现多行记录合并的几种方法...

    oracle某个字段多行记录转化为一行

    为了实现将Oracle数据库中某个字段的多行记录合并成一行记录的目标,可以采用编写自定义函数的方法。下面详细介绍该方法的具体步骤: #### 创建函数 `f_m_t` 首先,创建一个名为`f_m_t`的函数,该函数接受一个参数...

    oracle多行合并一行

    ### Oracle多行合并为一行的方法 在Oracle数据库中,有时候我们需要将多行数据合并成一行进行展示或处理,尤其是在报表生成、数据展示等场景中。本文将详细介绍如何使用Oracle纯SQL语句实现这一功能,并通过具体...

    oracle实现多行合并的方法

    本文实例讲述了oracle实现多行合并的方法。分享给大家供大家参考。具体分析如下: 在写sql时,经常会有将某列的字段合并起来,比如将某人名下每个月的工资列示,但是每个人只能占一行。 像这种场景,可能用行列转换...

    PLSQL单行函数和组函数详解

    在Oracle的PL/SQL编程中,函数是极其重要的组成部分,它们用于处理和操作数据。本篇文章将详细讲解PL/SQL中的单行函数和组函数。 首先,单行函数是针对单行数据进行操作的函数,它们可以应用于SQL查询的不同部分,...

    oracle实现行转列功能,并使用逗号进行隔开拼接,成为一条数据.pdf

    Oracle 中实现行转列功能,并使用逗号进行隔开拼接,成为一条数据是指将多行数据合并成一行数据,并用逗号分隔每个字段的值。这种功能在实际应用中非常有用,例如在报表生成、数据分析和数据整合等场景中。 在 ...

    oracle将以逗号分隔字符串转多行

    在Oracle数据库中,将逗号分隔的字符串转换为多行是常见的数据处理需求,尤其在需要对每个分隔项进行单独操作时。这个过程通常涉及到字符串处理函数,如`REGEXP_SUBSTR`和`REPLACE`,以及层次查询结构`CONNECT BY`。...

    Oracle 多行记录合并/连接/聚合字符串的几种方法

    在Oracle数据库中,合并多行记录的字符串是一个常见的需求,特别是在报表或数据分析中。这个问题涉及到字符串的连接和聚合,使得多个记录的某个字段值能够整合到一行。在Oracle中,虽然没有内置的聚合函数直接支持...

    Sql function 多行中的列合并为一行一列的方法

    总结来说,这个示例展示了一种使用SQL自定义函数将多行数据合并为一行的方法,这在处理多值字段时非常有用,但需要注意性能和数据长度限制。在实际应用中,根据数据库系统的特性选择最适合的解决方案是至关重要的。

    Oracle行转列

    Oracle行转列是指在Oracle数据库中将行数据转换为列数据或将列数据转换为行数据的操作。这种操作在实际应用中非常有用,例如,在数据报表、数据分析和数据挖掘等领域都需要使用行转列操作。 1. 列转行 列转行是指...

    oracle行列转换实例

    - 进行行列转换的具体实现通常涉及多个步骤,包括找出关键字的属性个数,创建新的列,使用分析函数定位属性的位置,最后将多行数据合并为一列。具体的 SQL 语句可能会根据实际数据结构和需求有所不同,但主要思路是...

    sql里将重复行数据合并为一行数据使用逗号进行分隔

    在SQL中,有时我们需要将具有相同属性的重复行数据合并成一行,并使用特定的分隔符,如逗号,来区分各个值。这种操作在处理报告或者数据分析时非常常见,可以减少数据的冗余,使结果更加简洁。本文将详细讲解如何在...

    oracle-函数.pptx

    在Oracle中,有一个特殊的表`DUAL`,它只有一个名为`DUMMY`的列和一行数据。当你只需要执行一次计算,而不需要从实际表中获取数据时,可以使用`DUAL`表。例如,要获取当前日期,可以这样写: ```sql SELECT SYSDATE...

    Oracle内建函数大全

    以上只是Oracle内建函数的一部分,实际中还有许多其他函数,如位运算函数、分析函数、游标函数等,它们极大地增强了SQL语言的功能,使得Oracle数据库能够处理各种复杂的数据操作。Oracle Built-in Functions.chm文件...

    oracle数据行列转换

    在实际业务场景中,有时我们需要将多行数据合并到一列,或者将一列数据分散到多行,以适应不同的分析需求。例如,一个销售报表可能需要按产品分类显示每个月的销售额,这时就需要将时间轴(月份)转换为列,而产品则...

    oracle_lhr_行列互换总结

    这通常在每行数据中,使用group by和聚合函数max或min等来实现,将多个值合并为一个字符串。 5. 字符串转换成多列 字符串转换成多列是指将一个字符串拆分为多个列的过程。可以通过正则表达式来匹配特定模式的字符串...

    Oracle函数与查询.pptx

    OLAP函数用于复杂的分析操作,如LEAD和LAG函数获取当前行前后行的值,RANK、DENSE_RANK和ROW_NUMBER用于行号分配,FIRST_VALUE和LAST_VALUE获取分组内第一行或最后一行的值。 7. **查询优化**: 在实际查询中,...

    oracle语法大全

    这种方法利用了窗口函数`ROW_NUMBER()`来为每行分配一个序号,然后通过自连接找到相邻的行,最后使用`STRING_AGG`(这是一个模拟的函数,实际的Oracle中没有,但可以使用其他方法实现类似效果)进行合并。...

    oracle练习_面试题

    行转列可以用来将多行记录转换为一行记录,使用 MAX 函数可以实现此操作。 示例: ```sql SELECT MAX(DECODE(deptno, 10, '部门 10', 20, '部门 20', 30, '部门 30', '其他部门')) FROM emp; ``` Oracle 实践面试...

Global site tag (gtag.js) - Google Analytics