广

oracle数据库

  • MYSQL
  • MSSQL
  • Redis
  • MongoDB
  • oracle数据库
  • 数据管理

    oracle 树查询 语句

    2018-05-03 14:17:09 次阅读 稿源:互联网
    零七网广告
    全网推广平台,软文发布
    格式:
    SELECT column
    FROM table_name
    START WITH column=value
    CONNECT BY PRIOR 父主键=子外键
    select lpad(' ',4*(level-1))||name name,job,id,super from emp
    start with super is null
    connect by prior id=super
    例子:
    原始数据:select no,q from a_example2
    NO NAME
    ---------- ------------------------------
    001 a01
    001 a02
    001 a03
    001 a04
    001 a05
    002 b01
    003 c01
    003 c02
    004 d01
    005 e01
    005 e02
    005 e03
    005 e04
    005 e05
    需要实现得到结果是:
    001 a01;a02;a03
    002 b01
    003 c01;c02
    004 d01
    005 e01;e02;e03;e04;e05
    思路:
    1、ORACLE8.1之后有个connect by 子句,取出整棵树数据。
    create table a_example1
    (
    no char(3) not null,
    name varchar2(10) not null,
    parent char(3)
    )
    insert into a_example1
    values('001','老王',null)
    insert into a_example1
    values('101','老李',null)
    insert into a_example1
    values('002','大王1','001')
    insert into a_example1
    values('102','大李1','101')
    insert into a_example1
    values('003','大王2','001')
    insert into a_example1
    values('103','大李2','101')
    insert into a_example1
    values('003','小王1','002')
    insert into a_example1
    values('103','小李1','102')
    NO  NAME PARENT
    001 老王
    101 老李
    002 大王1 001
    102 大李1 101
    003 大王2 001
    103 大李2 101
    003 小王1 002
    103 小李1 102
    //按照家族树取数据
    select * from a_example1
    select level,sys_connect_by_path(name,'/') path
    from a_example1
    start with /*name = '老王' and*/ parent is null
    connect by parent = prior no
    结果:
    1 /老王
    2 /老王/大王1
    3 /老王/大王1/小王1
    2 /老王/大王2
    1 /老李
    2 /老李/大李1
    3 /老李/大李1/小李1
    2 /老李/大李2
    按照上面思路,我们只要将原始数据做成如下结构:
    NO NAME
    001 a01
    001 a01/a02
    001 a01/a02/a03
    001 a01/a02/a03/a04
    001 a01/a02/a03/a04/a05
    002 b01
    003 c01
    003 c01/c02
    004 d01
    005 e01
    005 e01/e02
    005 e01/e02/e03
    005 e01/e02/e03/e04
    005 e01/e02/e03/e04/e05
    最后按NO分组,取最大的一个值即为所需的结果。
    NO NAME
    001 a01/a02/a03/a04/a05
    002 b01
    003 c01/c02
    004 d01
    005 e01/e02/e03/e04/e05
    SQL语句:
    select no,max(sys_connect_by_path(name,';')) result from
    (select no,name,rn,lead(rn) over(partition by no order by rn) rn1
    from (select no,name,row_number() over(order by no,name desc) rn from a_example2)
    )
    start with rn1 is null connect by rn1 = prior rn
    group by no
    语句分析:
    1、 select no,name,row_number() over(order by no,name desc) rn from a_example2
    按照NO升序排序,同时按照NAME降序排序,产生伪列,目的是要形成树结构
    NO  NAME RN
    001 a03 1
    001 a02 2
    001 a01 3
    002 b01 4
    003 c02 5
    003 c01 6
    004 d01 7
    005 e05 8
    005 e04 9
    005 e03 10
    005 e02 11
    005 e01 12
    2、select no,name,rn,lead(rn) over(partition by no order by rn) rn1
    from ( select no,name,row_number() over(order by no,name desc) rn from a_example2)
    生成家族谱,即子节点与父节点有对应关系,对应关系通过rn和 rn1。其中lead为上一条记录的RN值
    NO  NAME RN  RN1  001 a03 1 2 --
    说明:针对NO=001来说,其下一条记录的RN=2 001 a02 2 3 --说明:针对NO=001来说,其下一条记录的RN=3 001 a01 3  --说明:针对NO=001来说,其下一条记录的RN IS NULL
    002 b01 4 003 c02 5 6 003 c01 6 004 d01 7 005 e05 8 9 005 e04 9 10 005 e03 10 11 005 e02 11 12 005 e01 12
    3、select no,sys_connect_by_path(name,';') result from
    (select no,name,rn,lead(rn) over(partition by no order by rn) rn1
    from ( select no,name,row_number() over(order by no,name desc) rn from a_example2))
    start with rn1 is null connect by rn1 = prior rn
    正式生成树
    NO   RESULT
    001 ;a01
    001 ;a01;a02
    001 ;a01;a02;a03
    002 ;b01
    005 ;e01
    005 ;e01;e02
    005 ;e01;e02;e03
    005 ;e01;e02;e03;e04
    005 ;e01;e02;e03;e04;e05
    003 ;c01
    003 ;c01;c02
    004 ;d01
    将上面结果按照NO分组,取result最大值即可,所以将上述语句改为
    select no,max(sys_connect_by_path(name,';')) result from
    (select no,name,rn,lead(rn) over(partition by no order by rn) rn1
    from (select no,name,row_number() over(order by no,name desc) rn from a_example2)
    )
    start with rn1 is null connect by rn1 = prior rn
    group by no
    得到所需结果。

    零七网部分新闻及文章转载自互联网,供读者交流和学习,若有涉及作者版权等问题请及时与我们联系,以便更正、删除或按规定办理。感谢所有提供资讯的网站,欢迎各类媒体与零七网进行文章共享合作。

    零七网广告
    零七网广告
    零七网广告
    零七网广告