connect by prior
1. connect by prior 介绍
语法
{ CONNECT BY [ NOCYCLE ] condition [AND condition]... [ START WITH condition ]
| START WITH condition CONNECT BY [ NOCYCLE ] condition [AND condition]...}解释:start with: 指定起始节点的条件connect by: 指定父子行的条件关系prior: 查询父行的限定符,格式: prior column1 = column2 or column1 = prior column2 and ... ,nocycle: 若数据表中存在循环行,那么不添加此关键字会报错,添加关键字后,便不会报错,但循环的两行只会显示其中的第一条循环行: 该行只有一个子行,而且子行又是该行的祖先行connect_by_iscycle: 前置条件:在使用了nocycle之后才能使用此关键字,用于表示是否是循环行,0表示否,1 表示是connect_by_isleaf: 是否是叶子节点,0表示否,1 表示是level: level伪列,表示层级,值越小层级越高,level=1为层级最高节点
个人理解:
connect by prior 是oracle 提供的一个查询表数据的树形结构的功能。
connect by prior 用法模式介绍:
connect by prior id = father_id start with id = x;
通过start with id=x 或者 start with father_id=x 获取第一行数据;
然后再通过connect by prior id = father_id 获取第二行及以后的数据,这里prior 表示之前
的意思,prior id = father_id 表示要取的father_id 的值来自上次取的id的值。
connect by prior id = father_id start with id = x0 可以这样递推:
根据id=x0 获取 对应的行1,
根据father_id = x0 获取对应的行2, 获取对应的id=x2;
根据father_id=x2 获取对应的行3,获取对应的id=x3;
…
示例:
create table t1(id int, father_id int);
insert into t1 values(1,0);
insert into t1 values(2,1);
insert into t1 values(12,1);
insert into t1 values(3,2);
insert into t1 values(102,101);SQL> select id, father_id, level from t1 connect by prior id = father_id start with id=1;ID FATHER_ID LEVEL
---------- ---------- ----------1 0 12 1 23 2 312 1 2SQL> select id, father_id, level from t1 connect by id = prior father_id start with id=2;ID FATHER_ID LEVEL
---------- ---------- ----------2 1 11 0 2增加一行,使出现循环
SQL> insert into t1 values(1,1);1 row created.SQL> select id, father_id, level from t1 connect by prior id = father_id start with id=1;
ERROR:
ORA-01436: CONNECT BY loop in user dataSQL> select id, father_id, level from t1 connect by nocycle prior id = father_id start with id=1;ID FATHER_ID LEVEL
---------- ---------- ----------1 0 12 1 23 2 312 1 21 1 12 1 23 2 312 1 2
::如果循环id=father_id 出现开头,如上,会出现2份。如果是中间出现的则忽略该行SQL> select * from t1 order by 1,2; ID FATHER_ID
---------- ----------1 02 12 23 24 312 1102 1017 rows selected.SQL> select id, father_id, level from t1 connect by nocycle prior id = father_id start with id=1;ID FATHER_ID LEVEL
---------- ---------- ----------1 0 12 1 23 2 34 3 412 1 2
2. 功能实现
初步实现connect by prior id=father_id start with id=x
#include <iostream>
#include <list>
using namespace std;typedef struct
{int id;int father_id;
}id_pid;/** show list node*/
void show_nodes(list<id_pid>&list_data)
{list<id_pid>::iterator it;cout<<"list node:"<<endl;for(it=list_data.begin(); it!=list_data.end(); it++){cout<<it->id<<'\t'<<it->father_id<<endl;}
}/** add node*/
void add_nodes(list<id_pid> &list_data)
{int i = 0;int total = 3;id_pid data_value;while(i++ < total){data_value.father_id = i;data_value.id = i+1;list_data.push_back(data_value);}
#if 1while(i++ < total+10){data_value.father_id = i;data_value.id=i+i%2;list_data.push_back(data_value);}
#endif
}/** get the first node*/
bool get_first_value(list<id_pid> &list_task1, list<id_pid>&list_data, int father_id)
{list<id_pid>::iterator it;for(it=list_data.begin(); it!=list_data.end(); it++){if(father_id == it->father_id){id_pid data_value;data_value.id = it->id;data_value.father_id = it->father_id;list_task1.push_back(data_value);it=list_data.erase(it);}}return list_data.size() == 0 ? false:true;
}/** connect by prior*/
void get_connect_by_prior(list<id_pid>&list_task1, list<id_pid> &list_data ,list<id_pid> &list_res)
{list<id_pid>::iterator it;int father_id;id_pid data_value;list<id_pid> list_task2;while(list_task1.size()>0){for(it=list_task1.begin(); it!=list_task1.end(); it++){data_value.id = it->id;data_value.father_id = it->father_id;list_res.push_back(data_value);father_id = it->id;get_first_value(list_task2, list_data, father_id);}list_task1 = list_task2;list_task2.clear();}}int main()
{list<id_pid> list_data;list<id_pid> list_task1;list<id_pid> list_res;add_nodes(list_data);show_nodes(list_data);get_first_value(list_task1, list_data, 1);get_connect_by_prior(list_task1, list_data, list_res);show_nodes(list_res);}
测试结果:
[wl@host122 cpp]$ ./connect1
list node:
2 1
3 2
4 3
6 5
6 6
8 7
8 8
10 9
10 10
12 11
12 12
14 13
result:
2 1
3 2
4 3
3. 语法改写 connect by prior
create table x1(id int, father_id int, name char(10), id4 int);
insert into x1 values(101, 100, 'n1', 1);
insert into x1 values(102, 101, 'n2', 2);
insert into x1 values(112, 101, 'n3', 3);
insert into x1 values(103, 102, 'n4', 4);
insert into x1 values(113, 112, 'n5', 5);
insert into x1 values(114, 113, 'n6', 6);
insert into x1 values(201, 200, 'n7', 7);
3.1 语法改写 connect by prior id = father_id start with father_id = 100
测试语句
select id, father_id, level from x1 connect by prior id = father_id
start with father_id = 100;
改写为mysql 支持的语句如下:
select id, father_id, level, pathlevel from
(select id, father_id,@le:= if (father_id = 100 , 1, if( locate( concat('|',father_id,':'), @pathlevel) > 0,substring_index( substring_index(@pathlevel,concat('|',father_id,':'),-1),'|',1) +1, -1) ) level,@pathlevel:= concat(@pathlevel,'|',id,':', @le ,'|') pathlevelfrom (select id, father_id from db2.x1 order by 1,2)temp1,(select @le := 1,@pathlevel := '')temp2
)xxx
where level > 0;
执行测试
oracle 执行结果
SQL> select id, father_id, level from x1 connect by prior id = father_id 2 start with father_id = 100; ID FATHER_ID LEVEL
---------- ---------- ----------101 100 1102 101 2103 102 3112 101 2113 112 3114 113 46 rows selected.mysql 执行结果
+------+-----------+-------+--------------------------------------------+
| id | father_id | level | pathlevel |
+------+-----------+-------+--------------------------------------------+
| 101 | 100 | 1 | |101:1| |
| 102 | 101 | 2 | |101:1||102:2| |
| 103 | 102 | 3 | |101:1||102:2||103:3| |
| 112 | 101 | 2 | |101:1||102:2||103:3||112:2| |
| 113 | 112 | 3 | |101:1||102:2||103:3||112:2||113:3| |
| 114 | 113 | 4 | |101:1||102:2||103:3||112:2||113:3||114:4| |
+------+-----------+-------+--------------------------------------------+
6 rows in set (0.01 sec)
3.2 语法改写 connect by prior id = father_id start with id = 101
测试语句
select id, father_id, level from x1 connect by prior id = father_id
start with id = 101;
改写为mysql 支持的语句如下:
select id, father_id, 1 as level, concat('|', id, ':0|') as pathlevel from db2.x1 where id = 101
union
select id, father_id, level, pathlevel from
(select id, father_id,@le:= if (father_id = 101 , 2, if( locate( concat('|',father_id,':'), @pathlevel) > 0,substring_index( substring_index(@pathlevel,concat('|',father_id,':'),-1),'|',1) +1, -1) ) level,@pathlevel:= if(@le = -1, @pathlevel, concat(@pathlevel,'|',id,':', @le ,'|')) pathlevelfrom (select id, father_id from db2.x1 where id != 101 order by 1,2)temp1,(select @le := 2,@pathlevel := '|101:0|')temp2
)xxx
where level > 0;
执行测试
oracle 执行结果
SQL> select id, father_id, level from x1 connect by prior id = father_id start with id=101;ID FATHER_ID LEVEL
---------- ---------- ----------101 100 1102 101 2103 102 3112 101 2113 112 3114 113 46 rows selected.mysql 执行结果
+------+-----------+-------+--------------------------------------------+
| id | father_id | level | pathlevel |
+------+-----------+-------+--------------------------------------------+
| 101 | 100 | 1 | |101:0| |
| 102 | 101 | 2 | |101:0||102:2| |
| 103 | 102 | 3 | |101:0||102:2||103:3| |
| 112 | 101 | 2 | |101:0||102:2||103:3||112:2| |
| 113 | 112 | 3 | |101:0||102:2||103:3||112:2||113:3| |
| 114 | 113 | 4 | |101:0||102:2||103:3||112:2||113:3||114:4| |
+------+-----------+-------+--------------------------------------------+
6 rows in set (0.00 sec)
4. sys_connect_by_path
4.1 sys_connect_by_path … start with father_id = x
测试语句
select id, father_id, level, sys_connect_by_path(id, ‘/’) as paths from x1
connect by prior id = father_id
start with father_id = 100;
等价写法:
select id, father_id, level, pathnodes from
(select id, father_id,@le:= if (father_id = 100 , 1, if( locate( concat('|',father_id,':'), @pathlevel) > 0,substring_index( substring_index(@pathlevel,concat('|',father_id,':'),-1),'|',1) +1, -1) ) level,@pathlevel:= if(@le = -1, @pathlevel, concat(@pathlevel,'|',id,':', @le ,'|')) pathlevel,@pathnodes:= if( father_id = 100, concat('/', id), concat_ws('/',if( locate( concat('|',father_id,':'),@pathall) > 0 , substring_index( substring_index(@pathall,concat('|', father_id, ':'),-1),'|',1),@pathnodes ) ,id ) )pathnodes,@pathall:=concat(@pathall,'|',id,':', @pathnodes ,'|') pathall from (select id, father_id from db2.x1 order by 1,2)temp1,(select @le := 1,@pathlevel := '',@pathall:='',@pathnodes:='')temp2
)xxx
where level > 0;
测试结果
oracle 执行结果101 100 1 /101102 101 2 /101/102103 102 3 /101/102/103112 101 2 /101/112113 112 3 /101/112/113114 113 4 /101/112/113/1146 rows selected.mysql 执行结果+------+-----------+-------+------------------+
| id | father_id | level | pathnodes |
+------+-----------+-------+------------------+
| 101 | 100 | 1 | /101 |
| 102 | 101 | 2 | /101/102 |
| 103 | 102 | 3 | /101/102/103 |
| 112 | 101 | 2 | /101/112 |
| 113 | 112 | 3 | /101/112/113 |
| 114 | 113 | 4 | /101/112/113/114 |
+------+-----------+-------+------------------+
6 rows in set (0.01 sec)
4.2 sys_connect_by_path … start with id = x
测试语句
select id, father_id, level, sys_connect_by_path(id, ‘/’) as paths from x1
connect by prior id = father_id
start with id = 101;
等价写法:
select id, father_id, 1 as level, concat('|', id, ':1') as pathlevel, concat('/', id) as pathnodesfrom db2.x1 where id = 101union
select id, father_id, level, pathlevel, pathnodes from
(select id, father_id,@le:= if (father_id = 101 , 2, if( locate( concat('|',father_id,':'), @pathlevel) > 0,substring_index( substring_index(@pathlevel,concat('|',father_id,':'),-1),'|',1) +1, -1) ) level,@pathlevel:= if(@le = -1, @pathlevel, concat(@pathlevel,'|',id,':', @le ,'|')) pathlevel,@pathnodes:= if( father_id = 101, concat('/101/', id), concat_ws('/',if( locate( concat('|',father_id,':'),@pathall) > 0 , substring_index( substring_index(@pathall,concat('|', father_id, ':'),-1),'|',1),@pathnodes ) ,id ) )pathnodes,@pathall:=concat(@pathall,'|',id,':', @pathnodes ,'|') pathall from (select id, father_id from db2.x1 where id != 101 order by 1,2)temp1,(select @le := 1,@pathlevel := '|101:1',@pathall:='',@pathnodes:='')temp2
)xxx
where level > 0;
测试结果
oracle101 100 1 /101102 101 2 /101/102103 102 3 /101/102/103112 101 2 /101/112113 112 3 /101/112/113114 113 4 /101/112/113/1146 rows selected.mysql 执行结果
+------+-----------+-------+-------------------------------------------+------------------+
| id | father_id | level | pathlevel | pathnodes |
+------+-----------+-------+-------------------------------------------+------------------+
| 101 | 100 | 1 | |101:1 | /101 |
| 102 | 101 | 2 | |101:1|102:2| | /101/102 |
| 103 | 102 | 3 | |101:1|102:2||103:3| | /101/102/103 |
| 112 | 101 | 2 | |101:1|102:2||103:3||112:2| | /101/112 |
| 113 | 112 | 3 | |101:1|102:2||103:3||112:2||113:3| | /101/112/113 |
| 114 | 113 | 4 | |101:1|102:2||103:3||112:2||113:3||114:4| | /101/112/113/114 |
+------+-----------+-------+-------------------------------------------+------------------+
6 rows in set (0.01 sec)
connect by prior相关推荐
- Oracle 树操作(select…start with…connect by…prior)
oracle树查询的最重要的就是select-start with-connect by-prior语法了.依托于该语法,我们可以将一个表形结构的以树的顺序列出来.在下面列述了oracle中树型查询的 ...
- 用select 语句中的START WITH...CONNECT BY PRIOR子句实现递归查询
from http://www.javaeye.com/topic/184074 今天发现在oracle中的select语句可以用START WITH...CONNECT BY PRIOR子句实现递归 ...
- SQL基础--层次化查询(START BY ... CONNECT BY PRIOR)
为什么80%的码农都做不了架构师?>>> --====================================================== --SQL基础--& ...
- Oracle中start with...connect by prior子句用法
http://www.cnblogs.com/ZHF/archive/2008/09/10/1288101.html Oracle中start with...connect by prior子句用法 ...
- 在oracle中通过connect by prior来实现递归查询!
connect by 是结构化查询中用到的,其基本语法是: select ... from tablename start by cond1 connect by cond2 where cond3; ...
- oracle中用START WITH...CONNECT BY PRIOR子句实现递归查询
今天发现在oracle中的select语句可以用START WITH...CONNECT BY PRIOR子句实现递归查询,connect by 是结构化查询中用到的,其基本语法是: select . ...
- oracle中 sql语句:start with .. connect by prior.. 用法
前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家.点击跳转到教程. 我们经常会将一个比较复杂的目录树存储到一个表中.或者将一些部门存储到一个表中,而这些部门互相有隶属关 ...
- oracle sql 语句 start with ...... connect by prior .......
这个查询条件可以理解为递归查询 select up_unit_code from pmctl_nuit START WITH unit_code = '1188899Q' CONNECT ...
- Oracle中start with xx connect by prior 语句解析
Oracle中start with xx connect by prior 语句解析 Oracle这种的start with语句主要对B型树的数据进行递归查询.可以指定数据树上的任一节点,然后查找 ...
- 数据库学习笔记---SQL基础-->层次化查询(START BY ... CONNECT BY PRIOR)
SQL基础-->层次化查询(START BY ... CONNECT BY PRIOR) 技术qq交流群:JavaDream:251572072 教程下载,在线交流:创梦IT社区:______ ...
最新文章
- 解决iscroll.js上拉下拉刷新手指划出屏幕页面无法回弹问题
- IDEA工具创建项目并提交码云和一些基本使用
- 算法导论13-1节习题解答
- 切面是异步还是同步操作‘_细说JS异步发展历程
- 有关判读flex 模板载入是否结束的一些问题。
- C# 汉字转拼音(支持GB2312字符集中所有汉字)
- JS动态添加Html
- Skype for Linux下载地址
- 【渝粤题库】陕西师范大学163208 饭店管理 作业
- 开调查公司创业,他的公司营业额达80万
- 1754. 骑士精神
- 云栖大会压轴好戏 阿里云发布视频云V5计划与系列新产品
- 完整的次世代3D游戏建模制作流程,学习教程分享
- 比赛记录——记录一次失败的比赛,九坤量化验证码识别大赛
- 【ESP32_8266_MQTT篇】
- Spring Security安全框架
- 牛客网最全在线笔试、编程攻略(建议收藏)
- 奇异值分解(SVD)原理详解及推导
- java随堂练习09-面对对象,创建20个学生对象,学号为1到20,年级和成绩都由随机数确定。
- 专题·关基保护 | 国家关键信息基础设施安全保护的法治进展