详解Oracle递归算法--start with..connect by

概述

前面已经讲过start with..connect by的用法,可能很多朋友还是不太明白,这里主要用到的是Oracle递归算法原理,下面用实例来做个简单介绍。


概念

所谓递归算法,是指把问题转化为规模缩小了的同类问题的子问题。然后递归调用函数(或过程)来表示问题的解。递归过程一般通过函数或子过程来实现,下面演示下递归算法在oracle数据库树形结构表中的查询应用技术。

语法

select [level],column,expr... from table
 [where condition]
 start with condition
 connect by [prior column1 = column2 
 | column1 = prior column2];

例:

select * from table 
start with org_id = 'xxx' 
connect by prior org_id = parent_id;

简单说来是将一个树状结构存储在一张表里,比如一个表中存在两个字段: org_id,parent_id那么通过表示每一条记录的parent是谁,就可以形成一个树状结构,用上述语法的查询可以取得这棵树的所有记录。

其中:

条件1 是根结点的限定语句,当然可以放宽限定条件,以取得多个根结点,实际就是多棵树。 
 条件2 是连接条件,其中用PRIOR表示上一条记录,比如 CONNECT BY PRIOR org_id = parent_id就是说上一条记录的org_id 是本条记录的parent_id,即本记录的父亲是上一条记录。 
 条件3 是过滤条件,用于对返回的所有记录进行过滤。

简单介绍如下:

在扫描树结构表时,需要依此访问树结构的每个节点,一个节点只能访问一次,其访问的步骤如下:

第一步:从根节点开始;

第二步:访问该节点;

第三步:判断该节点有无未被访问的子节点,若有,则转向它最左侧的未被访问的子节,并执行第二步,否则执行第四步;

第四步:若该节点为根节点,则访问完毕,否则执行第五步;

第五步:返回到该节点的父节点,并执行第三步骤。

总之:扫描整个树结构的过程也即是中序遍历树的过程。


实例说明

1、查找empno=7369的员工的所有上级领导

select ename,empno,mgr from emp
start with empno=7369
connect by empno=prior mgr;

详解Oracle递归算法--start with..connect by

详解Oracle递归算法--start with..connect by

这样可能不太好理解,改写输出成这样的形式你们就懂了:

select ename,empno,mgr,
substr(sys_connect_by_path(ename,'->'),3) from emp
start with empno=7369
connect by empno=prior mgr;

详解Oracle递归算法--start with..connect by

这里用到了新的函数 sys_connect_by_path() 我的理解是根据什么的路径进行连接,如在前面我们根据ename将他们进行连接,后面的'->' 是指用->来连接他们,加上substr纯属为了好看。

2、查找empno=7839的员工的所有下属

SQL> col SYS_CONNECT_BY_PATH(ENAME,'->') for a50
select ename,empno,mgr,sys_connect_by_path(ename,'->')
from emp 
start with empno=7839
 connect by prior empno=mgr;

详解Oracle递归算法--start with..connect by

3、查询出下一个日期

with orders as( 
 select to_date('25-09-2018','dd-mm-yyyy') order_date,1000 product_id,20 qty from dual union all 
 select to_date('26-09-2018','dd-mm-yyyy'),2000,15 from dual union all 
 select to_date('27-09-2018','dd-mm-yyyy'),1000,8 from dual union all 
 select to_date('28-09-2018','dd-mm-yyyy'),2000,12 from dual union all 
 select to_date('29-09-2018','dd-mm-yyyy'),2000,2 from dual union all 
 select to_date('30-09-2018','dd-mm-yyyy'),1000,4 from dual) 
select product_id,order_date, 
 lead(order_date,1) over (order by order_date) next_order_date 
from orders;

详解Oracle递归算法--start with..connect by


篇幅有限,这里就举三个例子来做说明好了,大家有空可以自己写一下。后面会分享更多DBA方面的内容,感兴趣的朋友可以关注下!

详解Oracle递归算法--start with..connect by

相关推荐