赞
踩
如果表中存在层次数据,则可以使用层次化查询子句查询出表中行记录之间的层次关系
基本语法:
[ START WITH CONDITION1 ]
CONNECT BY [ NOCYCLE ] CONDITION2
示例:
select id,parentid,partname, level
from tabpart
start with id = 11
connect by nocycle prior id = parentid;
表中存在层次数据
数据之间的层次关系即父子关系,通过表中列与列间的关系来描述,如tabpart表中的id和parentid。id表示部门编号,parentid表示部门归属的更高层部门编号,在表的每一行中都有一个表示父节点的parentid(除根节点外),通过每个节点的父节点,就可以确定整个树结构。
CONNECT BY [ NOCYCLE ] CONDITION2 层次子句作用
CONDITION2 [PRIOR expr = expr] : 指定层次结构中父节点与子节点之之间的关系。
CONDITION2 中的 一元运算符 PRIORY 必须放置在连接关系的两列中某一个的前面。在连接关系中,除了可以使用列名外,还允许使用列表达式。
start with 子句为可选项,用来标识哪行作为查找树型结构的第一行(即根节点,可指定多个根节点)。若该子句被省略,则表示所有满足查询条件的行作为根节点。
-- sql 1
select id,parentid, level
from tabpart
start with parentid = 0
connect by prior id = parentid;
结果:
id parentid level
1 0 1
13 1 2
12 1 2
123 12 3
122 12 3
121 12 3
1213 121 4
1212 121 4
1211 121 4
11 1 2
113 11 3
112 11 3
111 11 3
分析
层次查询执行逻辑:
a.确定上一行(相对于步骤b中的当前行),若start with 子句存在,则以该语句确定的行为上一行,若不存在则将所有的数据行视为上一行。
b.从上一行出发,扫描除该行之外所有数据行。
c.匹配条件 prior id = parentid
注意 一元运算符 prior,意思是之前的,指上一行
当前行定义:步骤b中扫描得到的所有行中的某一行
匹配条件含义:当前行字段 parentid 的值等于上一行字段id中的值,若满足则取出该行,并将level + 1,匹配完所有行记录后,将满足条件的行作为上一行,执行步骤 b,c。直到所有行匹配结束。
--sql 2
select id,parentid, level
from tabpart
start with id = 1211
connect by prior parentid = id;
结果:
id parentid level
1211 121 1
121 12 2
12 1 3
1 0 4
分析
层次查询执行逻辑:
a.确定上一行(相对于步骤b中的当前行),若start with 子句存在,则以该语句确定的行为上一行,若不存在则将所有的数据行视为上一行。
b.从上一行出发,扫描除该行之外所有数据行。
c.匹配条件 parentid = id
注意 一元运算符 prior,意思是之前的,指上一行
当前行定义:步骤b中扫描得到的所有行中的某一行
匹配条件含义:当前行字段 id 的值等于上一行字段 parentid 中的值,若满足则取出该行,并将 level + 1,匹配完所有行记录后,将满足条件的行作为上一行,执行步骤 b,c。直到所有行匹配结束。
自顶向下,自下向上口诀:
start with child_id = 10 connect by [prior] child_id = [prior] parent_id
prior 和子列在一起,表示寻找它的子孙,即自顶向下;
-- 向下
select id,parentid, level
from tabpart
start with id = 12
connect by prior id = parentid;
prior 和父列在一起,表示开始寻找它的爸爸,即自下向上;
-- 向上
select id,parentid, level
from tabpart
start with id = 12
connect by id = prior parentid;
指示该层级之内递归查询的哪一步骤返回了行。即从start with的条件开始为第一层,每一迭代加一层。示例如上。
指示一行是否有一个还是其祖先的孩子。存在循环时,当出现该情况时,connect by子句应该加上NOCYCLE。
示例:
表中增加一行数据,使符合循环的要求,执行sql 1
-- sql 1
select id,parentid, level
from tabpart
start with parentid = 0
connect by prior id = parentid;
将报错:
26079: CONNECT BY 查询已导致循环。
加上NOCYCLE
select id,parentid, level, CONNECT_BY_ISCYCLE
from tabpart
start with parentid = 0
connect by nocycle prior id = parentid;
结果:
id parentid level connect_by_iscycle 1 0 1 0 13 1 2 0 12 1 2 0 123 12 3 0 122 12 3 0 121 12 3 0 1213 121 4 0 1212 121 4 0 1211 121 4 0 0 1211 5 1 11 1 2 0 113 11 3 0 112 11 3 0 111 11 3 0
指示一行在查询返回的行之中是否有任何的孩子。如果是leaf(叶子),返回1,否则返回0。
示例:
select id,parentid, level, CONNECT_BY_ISLEAF
from tabpart
start with parentid = 0
connect by prior id = parentid;
结果:
id parentid level connect_by_isleaf 1 0 1 0 13 1 2 1 12 1 2 0 123 12 3 1 122 12 3 1 121 12 3 0 1213 121 4 1 1212 121 4 1 1211 121 4 0 0 1211 5 0 11 1 2 0 113 11 3 1 112 11 3 1 111 11 3 1
可构建和返回一字符串,该字符串表示从指定的行到层级的根的路径。类似于wm_concat函数,按层次顺序拼接字段。
示例:
select id,parentid, level, SYS_CONNECT_BY_PATH(partname,'/')
from tabpart
start with parentid = 0
connect by nocycle prior id = parentid;
结果:
id parentid level expression_1 1 0 1 /总部 13 1 2 /总部/华东区 12 1 2 /总部/华南区 123 12 3 /总部/华南区/海南 122 12 3 /总部/华南区/广西 121 12 3 /总部/华南区/广东 1213 121 4 /总部/华南区/广东/佛山 1212 121 4 /总部/华南区/广东/深圳 1211 121 4 /总部/华南区/广东/广州 0 1211 5 /总部/华南区/广东/广州/天河 11 1 2 /总部/华北区 113 11 3 /总部/华北区/天津 112 11 3 /总部/华北区/河北 111 11 3 /总部/华北区/北京
对返回的每个级别的同一父母的兄弟行进行排序。
示例:
select id,parentid, level, partname
from tabpart
start with id = 1
connect by nocycle prior id = parentid
ORDER SIBLINGS BY id;
为其运算对象的根祖先返回一表达式。
示例:
select id,parentid, level, CONNECT_BY_ROOT partname
from tabpart
start with parentid = 0
connect by nocycle prior id = parentid;
结果:
id parentid level partname 1 0 1 总部 13 1 2 总部 12 1 2 总部 123 12 3 总部 122 12 3 总部 121 12 3 总部 1213 121 4 总部 1212 121 4 总部 1211 121 4 总部 0 1211 5 总部 11 1 2 总部 113 11 3 总部 112 11 3 总部 111 11 3 总部
引用从前一递归步骤返回的值(此处的“步骤”是指该递归查询的一次迭代)。
参见第二部分。
递归查询路径
select id,parentid,partname, level
from tabpart
start with id = 1212
connect by nocycle id = prior parentid
order by level desc;
结果:
id parentid partnum level
1 0 总部 4
12 1 华南区 3
121 12 广东 2
1211 121 广州 1
自下而上,使用SYS_CONNECT_BY_PATH,获取的结果并不是需要的自上而下的顺序。这里可以使用wm_concat来拼接。
select replace(wm_concat(partname),',',' -> ')
from (
select id,parentid, partname, level
from tabpart
start with id = 1211
connect by nocycle id = prior parentid
order by level desc
);
结果:
(expression) 总部 -> 华南区 -> 广东 -> 广州
涉及到的表结构及语句
drop table if exists tabpart; create table tabpart(id int, parentid int, partname varchar(200),primary key(id)); insert into tabpart values(1,0,'总部'); insert into tabpart values(11,1,'华北区'); insert into tabpart values(12,1,'华南区'); insert into tabpart values(13,1,'华东区'); insert into tabpart values(111,11,'北京'); insert into tabpart values(112,11,'河北'); insert into tabpart values(113,11,'天津'); insert into tabpart values(121,12,'广东'); insert into tabpart values(122,12,'广西'); insert into tabpart values(123,12,'海南'); insert into tabpart values(1211,121,'广州'); insert into tabpart values(1212,121,'深圳'); insert into tabpart values(1213,121,'佛山'); -- 增加一行,用于循环 insert into tabpart values(0,1211,'天河区'); -- 修改为正确值 update tabpart set id = 12111 where id = 0;
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。