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相关推荐

  1. Oracle 树操作(select…start with…connect by…prior)

    oracle树查询的最重要的就是select-start with-connect by-prior语法了.依托于该语法,我们可以将一个表形结构的以树的顺序列出来.在下面列述了oracle中树型查询的 ...

  2. 用select 语句中的START WITH...CONNECT BY PRIOR子句实现递归查询

    from http://www.javaeye.com/topic/184074 今天发现在oracle中的select语句可以用START WITH...CONNECT BY PRIOR子句实现递归 ...

  3. SQL基础--层次化查询(START BY ... CONNECT BY PRIOR)

    为什么80%的码农都做不了架构师?>>>    --====================================================== --SQL基础--& ...

  4. Oracle中start with...connect by prior子句用法

    http://www.cnblogs.com/ZHF/archive/2008/09/10/1288101.html Oracle中start with...connect by prior子句用法 ...

  5. 在oracle中通过connect by prior来实现递归查询!

    connect by 是结构化查询中用到的,其基本语法是: select ... from tablename start by cond1 connect by cond2 where cond3; ...

  6. oracle中用START WITH...CONNECT BY PRIOR子句实现递归查询

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

  7. oracle中 sql语句:start with .. connect by prior.. 用法

    前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家.点击跳转到教程. 我们经常会将一个比较复杂的目录树存储到一个表中.或者将一些部门存储到一个表中,而这些部门互相有隶属关 ...

  8. oracle sql 语句 start with ...... connect by prior .......

    这个查询条件可以理解为递归查询 select  up_unit_code  from pmctl_nuit  START  WITH  unit_code = '1188899Q'   CONNECT ...

  9. Oracle中start with xx connect by prior 语句解析

    Oracle中start with xx connect by prior 语句解析 ​ Oracle这种的start with语句主要对B型树的数据进行递归查询.可以指定数据树上的任一节点,然后查找 ...

  10. 数据库学习笔记---SQL基础-->层次化查询(START BY ... CONNECT BY PRIOR)

    SQL基础-->层次化查询(START BY ... CONNECT BY PRIOR) 技术qq交流群:JavaDream:251572072  教程下载,在线交流:创梦IT社区:______ ...

最新文章

  1. 解决iscroll.js上拉下拉刷新手指划出屏幕页面无法回弹问题
  2. IDEA工具创建项目并提交码云和一些基本使用
  3. 算法导论13-1节习题解答
  4. 切面是异步还是同步操作‘_细说JS异步发展历程
  5. 有关判读flex 模板载入是否结束的一些问题。
  6. C# 汉字转拼音(支持GB2312字符集中所有汉字)
  7. JS动态添加Html
  8. Skype for Linux下载地址
  9. 【渝粤题库】陕西师范大学163208 饭店管理 作业
  10. 开调查公司创业,他的公司营业额达80万
  11. 1754. 骑士精神
  12. 云栖大会压轴好戏 阿里云发布视频云V5计划与系列新产品
  13. 完整的次世代3D游戏建模制作流程,学习教程分享
  14. 比赛记录——记录一次失败的比赛,九坤量化验证码识别大赛
  15. 【ESP32_8266_MQTT篇】
  16. Spring Security安全框架
  17. 牛客网最全在线笔试、编程攻略(建议收藏)
  18. 奇异值分解(SVD)原理详解及推导
  19. java随堂练习09-面对对象,创建20个学生对象,学号为1到20,年级和成绩都由随机数确定。
  20. 专题·关基保护 | 国家关键信息基础设施安全保护的法治进展

热门文章

  1. RTP-RTCP协议分析
  2. js文件 本地 上传服务器地址,js 本地文件同步服务器地址
  3. pycharm中安装pymysql
  4. LVGL (7) 显示对接
  5. 发表论文怎样确定刊物的级别
  6. pandas dataframe删除空行或者空列dropna,一般删除指定行或者列drop
  7. HTML5基础(五)零基础入门 (上)
  8. 计算机求职面试智力题:找毒药(一共n瓶水,仅有一瓶是毒药),求至少需要多少只老鼠/猪;或者求x只老鼠/猪最多可以搜索多少瓶水
  9. 学习使用php实现无限极评论和无限极转二级评论解决方案
  10. 《数据结构》实验二:线性表的实验(实验报告)