oracle子递归查询语句的几个有用的属性

1.如何正确排序:  siblings 
       2.展现路径:  SYS_CONNECT_BY_PATH
       3.条件的执行顺序



  先准备一下测试用的数据:

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->   SELECT  FUNC_ID, SUPER_ID, NAME
    
FROM  MGR_PURV_FUNCTION
 START 
WITH  FUNC_ID  =   5
CONNECT 
BY  PRIOR FUNC_ID  =  SUPER_ID
FUNC_IDSUPER_IDNAMEORDER_ID
10根配置0
111配置121
11111具体配置16
11211具体配置25
14112具体配置分支13
115112具体配置分支27
11611具体配置38
117116具体配置分支39
121配置21
12812具体配置1110
12312具体配置1214

    下面偶来讲具体内容:
  1.正确排序:  siblings 
             我们通常使用order by进行排序:            

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->   SELECT  FUNC_ID, SUPER_ID, NAME,ORDER_ID
    
FROM  tmp_test2
 START 
WITH  FUNC_ID  =   1
CONNECT 
BY  PRIOR FUNC_ID  =  SUPER_ID
order   by  order_id;

            但是这得到的结果是不正确的,因为order by在oracle的sql执行引擎中是最后被执行,其结果如下:

FUNC_IDSUPER_IDNAMEORDER_ID
10根配置0
121配置21
14112具体配置分支13
11211具体配置25
11111具体配置16
115112具体配置分支27
11611具体配置38
117116具体配置分支39
12812具体配置1110
12312具体配置1214
111配置121

            要得到正确的结果集,需要引入siblings,其在oracle的sql执行引擎的递归过程中发挥作用,因此结果正确,使用sql和查询结果如下:

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->   SELECT  FUNC_ID, SUPER_ID, NAME,ORDER_ID
2      FROM  tmp_test2
3  START  WITH  FUNC_ID  =   1
4 CONNECT  BY  PRIOR FUNC_ID  =  SUPER_ID
5 order  siblings  by  order_id;
FUNC_IDSUPER_IDNAMEORDER_ID
10根配置0
121配置21
12812具体配置1110
12312具体配置1214
111配置121
11211具体配置25
14112具体配置分支13
115112具体配置分支27
11111具体配置16
11611具体配置38
117116具体配置分支39

       2.展现路径:  SYS_CONNECT_BY_PATH
             有时候我们需要通过sql来直接展示节点的层次结构,一般的做法是通过伪列level和lpad来构造分割符来构造树的视觉效果,结果类似以下列表:

根配置
  配置2
    具体配置11
    具体配置12
  配置1
    具体配置2
      具体配置分支1
      具体配置分支2
    具体配置1
    具体配置3
      具体配置分支3

            其实oracle提供了原生的方法支持此类需求,而且效果更好,那就是函数sys_connect_by_path,使用sql和结果如下:

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--> SELECT  FUNC_ID, SUPER_ID, NAME, ORDER_ID, SUBSTR(SYS_CONNECT_BY_PATH(NAME,  ' -> ' ),  3 ) REMARK
    
FROM  TMP_TEST2
 START 
WITH  FUNC_ID  =   1
CONNECT 
BY  PRIOR FUNC_ID  =  SUPER_ID
 
ORDER  SIBLINGS  BY  ORDER_ID;

 

FUNC_ID

SUPER_ID

NAME

ORDER_ID

remark

10根配置0根配置
121配置21根配置->配置2
12812具体配置1110根配置->配置2->具体配置11
12312具体配置1214根配置->配置2->具体配置12
111配置121根配置->配置1
11211具体配置25根配置->配置1->具体配置2
14112具体配置分支13根配置->配置1->具体配置2->具体配置分支1
115112具体配置分支27根配置->配置1->具体配置2->具体配置分支2
11111具体配置16根配置->配置1->具体配置1
11611具体配置38根配置->配置1->具体配置3
117116具体配置分支39根配置->配置1->具体配置3->具体配置分支3

 

 

 


            这点其实在“ 递归查询遍历详解”已经提及了,但是有兄弟经常会搞错
            首先是要注意子句的语法书写顺序: select -> from -> where -> start with -> connect by -> order by
            where写在connect by后面就不行,报错。

 

 

            其次要注意子句的执行顺序:from -> start with -> connect by -> where -> select -> order by
            执行顺序where在connect by之后,因此如果需要过滤出数据在进行递归查询,一定要将放到一个子查询结果中才行

           4、level

例子 create table tmp_test
(id number,
name varchar2(20),
pid number);

插入一些数据 ,如
1 A 0
2 B 1
3 C 2
4 D 3
5 E 3
6 F 4
7 G 5
8 H 1

select a.*,level from tmp_test a
start with id=1
connect by prior id=pid ;
执行结果
ID NAME PID LEVEL
1 A 0 1
2 B 1 2
3 C 2 3
4 D 3 4
6 F 4 5
5 E 3 4
7 G 5 5
8 H 1 2

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Oracle查询是指在一个表中,某一行的值关联到该表中的另一行,而这个关联是可以归进行的。Oracle提供了几种查询的方法,包括使用CONNECT BY、WITH RECURSIVE以及PL/SQL等。下面分别介绍一下这几种方法的使用。 1. 使用CONNECT BY进行查询 CONNECT BY是Oracle提供的一种查询方法,可以用于查询树形结构、层次结构等具有层级关系的数据。其基本语法如下: ``` SELECT column1, column2, ... FROM table_name START WITH condition CONNECT BY [NOCYCLE] PRIOR column1 = column2; ``` 其中,START WITH是起始条件,CONNECT BY是归条件,NOCYCLE是可选的,用于避免出现环路。PRIOR是关键字,表示归的上一级。 举个例,假设我们有一个表emp,其中包含员工编号、员工姓名、直接上级编号等字段。我们可以使用如下语句查询某个员工的所有下属: ``` SELECT emp_name FROM emp START WITH emp_id = 1 CONNECT BY PRIOR emp_id = mgr_id; ``` 这段代码的意思是,找到emp_id为1的员工,然后查询该员工的所有下属,直到没有下属为止。 2. 使用WITH RECURSIVE进行查询 WITH RECURSIVE是SQL标准中定义的一种查询方法,可以用于查询树形结构、层次结构等具有层级关系的数据。其基本语法如下: ``` WITH RECURSIVE cte_name(column1, column2, ...) AS ( SELECT column1, column2, ... FROM table_name WHERE condition UNION ALL SELECT column1, column2, ... FROM table_name, cte_name WHERE condition ) SELECT column1, column2, ... FROM cte_name; ``` 其中,cte_name是WITH句中查询的名称,column1、column2等是需要查询的字段,table_name是要查询的表名,condition是查询条件。 举个例,我们可以使用如下语句查询某个员工的所有下属: ``` WITH RECURSIVE cte(emp_id, emp_name, mgr_id) AS ( SELECT emp_id, emp_name, mgr_id FROM emp WHERE emp_id = 1 UNION ALL SELECT emp.emp_id, emp.emp_name, emp.mgr_id FROM emp, cte WHERE emp.mgr_id = cte.emp_id ) SELECT emp_name FROM cte; ``` 这段代码的意思是,先找到emp_id为1的员工,然后查询该员工的所有下属,直到没有下属为止。 3. 使用PL/SQL进行查询 在PL/SQL中,我们可以使用循环或归函数进行查询。举个例,我们可以使用如下函数查询某个员工的所有下属: ``` CREATE OR REPLACE FUNCTION get_subordinates(p_emp_id NUMBER) RETURN SYS_REFCURSOR IS v_cursor SYS_REFCURSOR; BEGIN OPEN v_cursor FOR SELECT emp_name FROM emp WHERE mgr_id = p_emp_id; FOR emp IN v_cursor LOOP dbms_output.put_line(emp.emp_name); get_subordinates(emp.emp_id); END LOOP; RETURN v_cursor; END; ``` 这段代码的意思是,先查询mgr_id为指定员工编号的员工,然后逐个输出其下属的名字,并归调用自身查询下属的下属,直到没有下属为止。 以上是Oracle查询的几种方法,不同的方法适用于不同的情况。开发者可以根据实际需求选择最合适的方法。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值