Oracle中connectby...startwith...的使用
一、语法
大致写法:select*fromsome_table[where条件1]connectby[条件2]startwith[条件3];
其中connectby与startwith语句摆放的先后顺序不影响查询的结果,[where条件1]可以不需要。
[where条件1]、[条件2]、[条件3]各自作用的范围都不相同:
[where条件1]是在根据“connectby[条件2]startwith[条件3]”选择出来的记录中进行过滤,是针对单条记录的过滤,不会考虑树的结构;
[条件2]指定构造树的条件,以及对树分支的过滤条件,在这里执行的过滤会把符合条件的记录及其下的所有子节点都过滤掉;
[条件3]限定作为搜索起始点的条件,如果是自上而下的搜索则是限定作为根节点的条件,如果是自下而上的搜索则是限定作为叶子节点的条件;
示例:
假如有如下结构的表:some_table(id,p_id,name),其中p_id保存父记录的id。
select*fromsome_tabletwheret.id!=123connectbypriort.p_id=t.idandt.p_id!=321startwitht.p_id=33ort.p_id=66;
对prior的说明:
prior存在于[条件2]中,可以不要,不要的时候只能查找到符合“startwith[条件3]”的记录,不会在寻找这些记录的子节点。要的时候有两种写法:connectbypriort.p_id=t.id或connectbyt.p_id=priort.id,前一种写法表示采用自上而下的搜索方式(先找父节点然后找子节点),后一种写法表示采用自下而上的搜索方式(先找叶子节点然后找父节点)。
二、执行原理
connectby...startwith...的执行原理可以用以下一段程序的执行以及对存储过程RECURSE()的调用来说明:
/*遍历表中的每条记录,对比是否满足startwith后的条件,如果不满足则继续下一条,
如果满足则以该记录为根节点,然后调用RECURSE()递归寻找该节点下的子节点,
如此循环直到遍历完整个表的所有记录。*/
forrecin(select*fromsome_table)loop
ifFULLFILLS_START_WITH_CONDITION(rec)then
RECURSE(rec,rec.child);
endif;
endloop;
/*寻找子节点的存储过程*/
procedureRECURSE(recinMATCHES_SELECT_STMT,new_parentINfield_type)is
begin
APPEND_RESULT_LIST(rec);/*把记录加入结果集合中*/
/*再次遍历表中的所有记录,对比是否满足connectby后的条件,如果不满足则继续下一条,
如果满足则再以该记录为根节点,然后调用RECURSE()继续递归寻找该节点下的子节点,
如此循环直到找至叶子节点。*/
forrec_recursein(select*fromsome_table)loop
ifFULLFILLS_CONNECT_BY_CONDITION(rec_recurse.child,new_parent)then
RECURSE(rec_recurse,rec_recurse.child);
endif;
endloop;
endprocedureRECURSE;
三、使用探讨
从上面的执行原理可以看到“connectby...startwith...”构造树的方式是:(1)如果是自上而下方式,则把表中的每一条记录都作为根节点来生成树,所以表中有多少条记录就会构造出多少棵树。(2)如果是自下而上的搜索方式,则把表中的每一条记录都作为叶子节点来生成分支,所以表中有多少条记录就会生成多少条分支。
因此如果表中的记录不是严格遵照每条记录都只能有一个父记录的原则,那么就可能有部分记录会存在于多棵树中,那么在查找记录的时候就可能会出现找到多条重复记录的异常情况
--1.HierarchicalQueries:STARTWITHandCONNECTBYPRIORclauses
--HierarchicalQueries
--STARTWITHandCONNECTBYPRIORclauses.
SELECTemployee_id,manager_id,first_name,last_name
FROMemployee_jh
STARTWITHemployee_id=1
CONNECTBYPRIORemployee_id=manager_id;
EMPLOYEE_IDMANAGER_IDFIRST_NAMELAST_NAME
-----------------------------------------
10JamesSmith
21RonJohnson
32FredHobbs
52RobGreen
41SusanJones
64JaneBrown
96HenryHeyson
74JohnGrey
87JeanBlue
101KevinBlack
1110KeithLong
1210FrankHoward
1310DoreenPenn
13rowsselected.
--2.UsingaSubqueryinaSTARTWITHClause
SELECTLEVEL,
LPAD('',2*LEVEL-1)||first_name||''||last_nameASemployee
FROMemployee_jh
STARTWITHemployee_id=(SELECTemployee_idFROMemployee_jhWHEREfirst_name='Kevin'ANDlast_name='Black')
CONNECTBYPRIORemployee_id=manager_id;
LEVELEMPLOYEE
-----------------------------------
1KevinBlack
2KeithLong
2FrankHoward
2DoreenPenn
--3.IncludingOtherConditionsinaHierarchicalQuery
SELECTLEVEL,
LPAD('',2*LEVEL-1)||first_name||''||
last_nameASemployee,salary
FROMemployee_jh
WHEREsalary<=50000
STARTWITHemployee_id=1
CONNECTBYPRIORemployee_id=manager_id;
LEVELEMPLOYEESALARY
---------------------------------------------
3RobGreen40000
3JaneBrown45000
4HenryHeyson30000
3JohnGrey30000
4JeanBlue29000
3KeithLong50000
3FrankHoward45000
3DoreenPenn47000
8rowsselected.
分享到:
相关推荐
connect by prior数据库树的应用
Connect By 可以列出上下级关系 构造序列 求排列组合 逆转求出下上级的关系路径
在Oracle中用Start with...Connect By子句递归查询
本文章详细介绍了Oracle中connect by...start with...的用法。
Oracle start with.connect by prior子句实现递归查询
NULL 博文链接:https://sunyuzhou.iteye.com/blog/731222
NULL 博文链接:https://freejvm.iteye.com/blog/550858
connect by的使用探索
本文通过例子逐步描述如何将 CONNECT BY 语法和相关的伪列映射到 DB2® Universal Database™(DB2 UDB) for Linux®、UNIX® 和 Windows® 中的公共表表达式。
开发遇到一个报错 ORA-01436: CONNECT BY loop in user data (ORA-01436: 用户数据中的 CONNECT BY 循环)。 1. 报错原因 根据网上的资料,产生这个错误的原因是数据形成了循环。例如下面这个语句: SELECT r1....
Oracle Connect by
oracle中 connect by prior 递归算法 Oracle中start with...connect by prior子句用法 connect by 是结构化查询中用到的
NULL 博文链接:https://yunqiang-zhang-hotmail-com.iteye.com/blog/1312354
oracle connect by 和 分析函数总结.doc
connect by:connect by是必须的,start with有些情况是可以省略的,或者直接start with 1=1不加限制 prior:prior关键字可以放在等号的前面,也可以放在等号的后面,表示的意义是不一样的,比如 prior id = pid,...
sql语句中的经常用到start connect by,这里简单介绍一下它的使用
Oracle 递归查询, start with connect by prior 用法 find_in_set 函数 concat,concat_ws,group_concat 函数 MySQL 自定义函数 手动实现 MySQL 递归查询 Oracle 递归查询 在 Oracle 中是通过 start ...
通过实例比较了 SYS_CONNECT_BY_PATH 和 CONNECT_BY_ROOT 的异同,和返回树形的数据结构
几乎可以从Internet上的任何位置单击鼠标右键,将有趣的内容发布到ConnectBy。 这包括图像,网页链接或文本“引号”。 增强您与世界分享您发现有趣事物的能力。 使您和其他ConnectBy成员可以更方便地了解全球社区。 ...