Oracle:关于分组后字段拼接的问题

关于分组后字段拼接的问题
 
作  者:  duanzilin (寻) 
信 誉 值:  120
所属论坛:  Oracle 基础和管理
问题点数:  200
回复次数:  29
发表时间:  2005-7-22 11:52:56 

最近在论坛上,经常会看到关于分组后字段拼接的问题,
大概是类似下列的情形:
SQL> select no,q from test
  2  /

NO         Q
---------- ------------------------------
001        n1
001        n2
001        n3
001        n4
001        n5
002        m1
003        t1
003        t2
003        t3
003        t4
003        t5
003        t6

12 rows selected

最后要得到类似于如下的结果:
001        n1;n2;n3;n4;n5
002        m1
003        t1;t2;t3;t4;t5;t6

  通常大家都认为这类问题无法用一句SQL解决,本来我也这么认为,可是今天无意中突然有了灵感,原来是可以这么做的:
  前几天有人提到过sys_connect_by_path的用法,我想这里是不是也能用到这个方法,如果能做到的话,不用函数或存贮过程也可以做到了;要 用到sys_connect_by_path,首先要自己构建树型的结构,并且树的每个分支都是单根的,例如1-〉2-〉3-〉4,不会存在1-〉 2,1-〉3的情况;
  我是这么构建树,很简单的,看下面的结果就会知道了:
SQL> select no,q,rn,lead(rn) over(partition by no order by rn) rn1
  2  from (select no,q,row_number() over(order by no,q desc) rn from test)
  3  /

NO         Q                                      RN        RN1
---------- ------------------------------ ---------- ----------
001        n5                                      1          2
001        n4                                      2          3
001        n3                                      3          4
001        n2                                      4          5
001        n1                                      5
002        m1                                      6
003        t6                                      7          8
003        t5                                      8          9
003        t4                                      9         10
003        t3                                     10         11
003        t2                                     11         12
003        t1                                     12

12 rows selected

有了这个树型的结构,接下来的事就好办了,只要取出拥有全路径的那个path,问题就解决了,先看no=‘001’的分组:
select no,sys_connect_by_path(q,';') result from
       (select no,q,rn,lead(rn) over(partition by no order by rn) rn1
       from (select no,q,row_number() over(order by no,q desc) rn from test)
       )
start with no = '001' and rn1 is null connect by rn1 = prior rn
SQL>
  6  /

NO         RESULT
---------- --------------------------------------------------------------------------------
001        ;n1
001        ;n1;n2
001        ;n1;n2;n3
001        ;n1;n2;n3;n4
001        ;n1;n2;n3;n4;n5

上面结果的最后1条就是我们要得结果了
要得到每组的结果,可以下面这样

select t.*,
       (
        select max(sys_connect_by_path(q,';')) result from
               (select no,q,rn,lead(rn) over(partition by no order by rn) rn1
               from (select no,q,row_number() over(order by no,q desc) rn from test)
               )
        start with no = t.no and rn1 is null connect by rn1 = prior rn
       ) value
from (select distinct no from test)  t

SQL>
 10  /

NO         VALUE
---------- --------------------------------------------------------------------------------
001        ;n1;n2;n3;n4;n5
002        ;m1
003        ;t1;t2;t3;t4;t5;t6

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值