详解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;
这样可能不太好理解,改写输出成这样的形式你们就懂了:
select ename,empno,mgr, substr(sys_connect_by_path(ename,'->'),3) from emp start with empno=7369 connect by empno=prior mgr;
这里用到了新的函数 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;
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;
篇幅有限,这里就举三个例子来做说明好了,大家有空可以自己写一下。后面会分享更多DBA方面的内容,感兴趣的朋友可以关注下!