星辰日月00

欲多则心散,心散则志衰,志衰则思不达也!

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

oracle中的select语句可以用START WITH...CONNECT BY PRIOR子句实现递归查询,connect by 是结构化查询中用到的,其基本语法是:

select ... from <TableName> 
where <Conditional-1>
start with <Conditional-2>
connect by <Conditional-3>;

<Conditional-1>:过滤条件,用于对返回的所有记录进行过滤。
<Conditional-2>:查询结果重起始根结点的限定条件。
<Conditional-3>:连接条件

 

简单说来是将一个树状结构存储在一张表里,比如一个表中存在两个字段:
org_id,parent_id那么通过表示每一条记录的parent是谁,就可以形成一个树状结构。
     用上述语法的查询可以取得这棵树的所有记录。
     其中:
     条件1 是根结点的限定语句,当然可以放宽限定条件,以取得多个根结点,实际就是多棵树。
     条件2 是连接条件,其中用PRIOR表示上一条记录,比如 CONNECT BY PRIOR org_id = parent_id就是说上一条记录的org_id 是本条记录的parent_id,即本记录的父亲是上一条记录。 注意CONNECT BY PRIOR org_id = parent_id 和 CONNECT BY  parent_id = PRIOR org_id的意思是一样的。
     条件3 是过滤条件,用于对返回的所有记录进行过滤。

     简单介绍如下:
     早扫描树结构表时,需要依此访问树结构的每个节点,一个节点只能访问一次,其访问的步骤如下:
     第一步:从根节点开始;
     第二步:访问该节点;
     第三步:判断该节点有无未被访问的子节点,若有,则转向它最左侧的未被访问的子节,并执行第二步,否则执行第四步;
     第四步:若该节点为根节点,则访问完毕,否则执行第五步;
     第五步:返回到该节点的父节点,并执行第三步骤。

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

 

 

数据组织结构如下图:

|---a------a1
|     |------a2
|
|---b------b1
      |------b2

数据库表结构如下:

create table t2(
  root_id number,
  id number,
  name varchar(5),
  description varchar(10)
);

insert into t2(root_id,id,name,description) values(0,1,'a','aaa');
insert into t2(root_id,id,name,description) values(1,2,'a1','aaa1');
insert into t2(root_id,id,name,description) values(1,3,'a2','aaa2');
insert into t2(root_id,id,name,description) values(0,4,'b','bbb');
insert into t2(root_id,id,name,description) values(4,5,'b1','bbb1');
insert into t2(root_id,id,name,description) values(4,6,'b2','bbb2');
SELECT LEVEL,                                                --LEVEL 伪列表示节点深度 
       RPAD( ' ', 2*(LEVEL-1), '-' ) || NAME "TreeNAME",     --如果' '少于2*(LEVEL-1)个字符,则向右补'-'
       t2.*, SYS_CONNECT_BY_PATH(t2.NAME, '/') "PATH"        --SYS_CONNECT_BY_PATH函数显示详细路径,并用“/”分隔
  FROM t2
 START WITH root_Id =0 
CONNECT BY root_Id = PRIOR ID

1. CONNECT_BY_ROOT 返回当前节点的最顶端节点 
2. CONNECT_BY_ISLEAF 判断是否为叶子节点,如果这个节点下面有子节点,则不为叶子节点 

 

 

 

SQL> select * from t2;

   ROOT_ID         ID NAME DESCRIPTIO
---------- ---------- ----- ----------
         0          1 a     aaa
         1          2 a1    aaa1
         1          3 a2    aaa2
         0          4 b     bbb
         4          5 b1    bbb1
         4          6 b2    bbb2
        
获取完整树:
select * from t2 start with root_id = 0 connect by prior id = root_id;

|---a------a1
|     |------a2
|
|---b------b1
      |------b2

   ROOT_ID         ID NAME DESCRIPTIO
---------- ---------- ----- ----------
         0          1 a     aaa
         1          2 a1    aaa1
         1          3 a2    aaa2
         0          4 b     bbb
         4          5 b1    bbb1
         4          6 b2    bbb2


获取特定子树:
select * from t2 start with id = 1 connect by prior id = root_id;

|---a------a1
|     |------a2

   ROOT_ID         ID NAME DESCRIPTIO
---------- ---------- ----- ----------
         0          1 a     aaa
         1          2 a1    aaa1
         1          3 a2    aaa2
        
select * from t2 start with id = 4 connect by prior id = root_id;

|---b------b1
      |------b2

   ROOT_ID         ID NAME DESCRIPTIO
---------- ---------- ----- ----------
         0          4 b     bbb
         4          5 b1    bbb1
         4          6 b2    bbb2
        
如果connect by prior中的prior被省略,则查询将不进行深层递归。
如:

select * from t2 start with root_id = 0 connect by id = root_id;

|---a
|   
|
|---b


   ROOT_ID         ID NAME DESCRIPTIO
---------- ---------- ----- ----------
         0          1 a     aaa
         0          4 b     bbb

如:        
select * from t2 start with id = 1 connect by id = root_id;


|---a

   ROOT_ID         ID NAME DESCRIPTIO
---------- ---------- ----- ----------
         0          1 a     aaa

posted on 2012-08-18 09:33  星辰日月00  阅读(270)  评论(0编辑  收藏  举报