start_with connect_by_prior

来源:互联网 发布:什么鼠标垫好用 知乎 编辑:程序博客网 时间:2024/06/10 23:12

    

这几个关键是查询递归数据的,形成一个树状结构。目前只有

oracle

支持,其他数据都要结合存储过程实现

 

语法:

 

select * from some_table [where 

条件

1] connect by [

条件

2] start with [

条件

3];

 

   

其中

 

connect by 

 

start with 

语句摆放的先后顺序不影响查询的结果,

[where 

条件

1]

可以不需要。

 

[where 

条件

1]

[

条件

2]

[

条件

3]

各自作用的范围都不相同:

 

     

 

[where 

条件

1]

是在根据

“connect by [

条件

2] start with [

条件

3]”

选择出来的记录中进行过滤,是针对单条记录的过滤,

 

不会考虑树的结构;

 

    

 

[

条件

2]

指定构造树的条件,以及对树分支的过滤条件,在这里执行的过滤会把符合条件的记录及其下的所有子节点都

过滤掉;

 

   

 

[

条件

3]

限定作为搜索起始点的条件,如果是自上而下的搜索则是限定作为根节点的条件,如果是自下而上的搜索则是

限定作为叶子节点的条件;

 

      

这几个关键是查询递归数据的,形成一个树状结构。目前只有oracle支持,其他数据都要结合存储过程实现

语法: select * from some_table[where 条件1]connect by [条件2]start with [条件3];

   其中connect by 与 start with 语句摆放的先后顺序不影响查询的结果,[where 条件1]可以不需要。[where 条件1]、[条件2]、[条件3]各自作用的范围都不相同:

     [where 条件1]是在根据“connectby [条件2] start with [条件3]”选择出来的记录中进行过滤,是针对单条记录的过滤, 不会考虑树的结构;

     [条件2]指定构造树的条件,以及对树分支的过滤条件,在这里执行的过滤会把符合条件的记录及其下的所有子节点都过滤掉;

    [条件3]限定作为搜索起始点的条件,如果是自上而下的搜索则是限定作为根节点的条件,如果是自下而上的搜索则是限定作为叶子节点的条件;

   

对prior的说明:prior存在于[条件2]中,可以不要,不要的时候只能查找到符合“start with [条件3]”的记录,不会在寻找这些记录的子节点。要的时候有两种写法:connect by prior empno=mgr 或connect by empno=prior mgr,前一种写法表示采用自上而下的搜索方式(先找父节点然后找子节点),后一种写法表示采用自下而上的搜索方式(先找叶子节点然后找父节点)


   [执行原理] 遍历表中的每条记录,对比是否满足start with后的条件,如果不满足则继续下一条, 如果满足则以该记录为根节点,然后递归寻找该节点下的子节点, 查找条件是connect by后面指定的条件,比如下面的例子,是当前记录的id等于其子节点的parentid,如此循环直到遍历完整个表的所有记录 如果数据有问题,出现循环,即a是b的经理,b是c的经理,c又是a的经理,查询会出现ORA-01436: 用户数据中的 CONNECT BY 循环 的错误,可在connectby后面添加nocycle 解决这个问题。

    结合sys_connect_by_path 函数,可以做出更好的效果



create table dept(id number(9) primary key,name varchar2(100),parentid number(9));

     insert into dept values(01,'管理部','');
     insert into dept values(02,'开发部','');
     insert into dept values(03,'测试部','');
     insert into dept values(04,'销售部','');
     insert into dept values(0201,'开发1部',02);
     insert into dept values(0202,'开发2部',02);
     insert into dept values(0203,'开发3部',02);
     insert into dept values(0301,'测试1部',03);
     insert into dept values(0302,'测试2部',03);
     insert into dept values(0401,'销售1部',04);
     insert into dept values(0402,'销售2部',04);
     insert into dept values(0403,'销售3部',04);
     insert into dept values(0404,'销售4部',04);
     insert into dept values(020101,'开发1部1组',0201);

     insert into dept values(020102,'开发1部2组',0201);


     查询语句(由根到叶):

     select * from dept a start with id=2 connect by prior a.id=a.parentid

    测试结果:

 IDNAMEPARENTID12开发部2201开发1部2320101开发1部1组201420102开发1部2组2015202开发2部26203开发3部2

     查询语句(说明where是对选择出来的结果再过滤):

     select * from dept a where a.name like '%组%' start with id=2 connect by prior a.id=a.parentid

    测试结果:

 IDNAMEPARENTID120101开发1部1组201220102开发1部2组201

      查询语句:

     select * from dept a  start with id=2 connect by  a.id=a.parentid

     测试结果:

 IDNAMEPARENTID12开发部

    查询语句(叶到根):

     select * from dept a start with id=20101 connect by a.id=  prior a.parentid

    测试结果:

 IDNAMEPARENTID120101开发1部1组2012201开发1部232开发部

      查询语句(结合sys_connect_by_path ):

     select id,name,sys_connect_by_path(name,'/') from dept start with name='开发部' CONNECT BY prior id=parentid;

      测试结果:

 IDNAMESYS_CONNECT_BY_PATH(NAME,'/')12开发部/开发部2201开发1部/开发部/开发1部320101开发1部1组/开发部/开发1部/开发1部1组420102开发1部2组/开发部/开发1部/开发1部2组5202开发2部/开发部/开发2部6203开发3部/开发部/开发3部


 


    

0 0
原创粉丝点击