一、概述

  1. Oracle中可以通过START WITH . . . CONNECT BY . . .子句来实现SQL的层次查询.
  2. 自从Oracle 9i开始,可以通过 SYS_CONNECT_BY_PATH 函数实现将父节点到当前行内容以“path”或者层次元素列表的形式显示出来。
  3. 自从Oracle 10g 中,还有其他更多关于层次查询的新特性 。例如,有的时候用户更关心的是每个层次分支中等级最低的内容。
    那么你就可以利用伪列函数CONNECT_BY_ISLEAF来判断当前行是不是叶子。如果是叶子就会在伪列中显示“1”,
    如果不是叶子而是一个分支(例如当前内容是其他行的父亲)就显示“0”。
  4. 在Oracle 10g 之前的版本中,如果在你的树中出现了环状循环(如一个孩子节点引用一个父亲节点),
    Oracle 就会报出一个错误提示:“ ORA-01436: CONNECT BY loop in user data”。如果不删掉对父亲的引用就无法执行查询操作。
    而在 Oracle 10g 中,只要指定“NOCYCLE”就可以进行任意的查询操作。与这个关键字相关的还有一个伪列——CONNECT_BY_ISCYCLE
    如果在当前行中引用了某个父亲节点的内容并在树中出现了循环,那么该行的伪列中就会显示“1”,否则就显示“0”。

层级查询的基本语法:

select [level],*  feom table_name  
start with 条件1
connect by [ nocycle ] prior 条件2
where 条件3 ORDER BY [ sibilings ] 排序字段

  说明:

  • start with condition1 是用来限制第一层的数据,或者叫根节点数据;以这部分数据为基础来查找第二层数据,然后以第二层数据查找第三层数据以此类推。
  • connect by [prior] id=parentid 连接条件,目的就是给出父子之间的关系是什么,根据这个关系进行递归查询
  • where 条件3---过滤条件,对所有返回的记录进行过滤。
  • order by 排序字段---对所有返回记录进行排序
  •   对prior说明:
    • connect by prior dept_id=par_dept_id :采用自上而下的搜索方式(先找父节点然后找叶子节点),比如说查找第二层的数据时用第一层数据的id去跟表里面记录的parentid字段进行匹配,匹配成功那么查找出来的就是第二层数据;
    • connect by dept_id=prior par_dept_id:采用自下而上的搜索方式(先找叶子节点然后找父节点)。 比如说用第一层数据的parentid去跟表记录里面的id进行匹配,匹配成功那么查找出来的就是第二层数据;
  • level关键字,LEVEL---伪列,用于表示树的层次 ,第一层是数字1,第二层数字2,依次递增。
  • CONNECT_BY_ROOT方法,能够获取第一层集结点结果集中的任意字段的值;例CONNECT_BY_ROOT(字段名)。

二、使用

1、基本用法

例1、 查询Raphaely及其的所有下属

select *  from employees
start with last_name = 'Raphaely'
connect by prior employee_id = manager_id; --找下属
-- connect by employee_id = prior manager_id;  --找上司,第一种,修改prior关键字位置
-- connect by prior manager_id = employee_id; --找上司,第二种,prior关键字不动 调换后面的 employee_id = manager_id 逻辑关系的顺序

例2、 查询除了Raphaely和他下属的所有员工

select * from employees
start with manager_id is null
connect by prior employee_id = manager_id and last_name <> 'Raphaely';

例3、 统计树形的层数

select count(distinct LEVEL)   from EMPLOYEES
start with MANAGER_ID is null
connect by prior EMPLOYEE_ID = MANAGER_ID;

例4、 过滤某些结果集,注意:where子句比connect by后执行。

查询Kochhar的所有下属中lastname为
Mavris雇员。

SELECT * FROM employees
WHERE last_name = 'Mavris'
START WITH last_name = 'Kochhar' --Kochhar的所有雇员
CONNECT BY PRIOR employee_id = manager_id;

例5、level伪列的使用,格式化层级

select lpad(' ',level*2,' ')||emp_name as name,emp_id,manager_id,salary,level from employee
start with manager_id=0
connect by prior emp_id=manager_id

2、SYS_CONNECT_BY_PATH() 函数

作用:  将父节点到当前节点的路径按照指定的模式展现出来,把一个父节点下的所有节点通过某个字符区分,然后链接在一个列中显示。

格式:

sys_connect_by_path(<列名>,<连接串>)
select sys_connect_by_path(t.dept_name,'-->'),t.dept_id, t.dept_name, t.dept_code,t.par_dept_id, level  from SYS_DEPT t
start with t.dept_id = 'e01d6'
connect by prior t.dept_id = t.par_dept_id
order by level, t.dept_code


3、CONNECT_BY_ISLEAF 伪列

作用:判断层次查询结果集中的行是不是叶子节点

返回值: 0表示不是叶子节点, 1表示是叶子节点

例:


4、CONNECT_BY_ROOT 字段x -> 找到该节点最顶端节点的字段x

select last_name "Employee", connect_by_root last_name "Manager",sys_connect_by_path(last_name, ' -> ') "Path" from hr.employees
where level > 1
connect by prior employee_id = manager_id
order by last_name, length("Path");

思考? 为什么不能加 start with ?  加了会有什么效果?

不加start with , 则每个节点都遍历一次 , connect_by_root 找到顶端的经理人会不同

而加了start with manager_id is null 则从树的根节点 King 开始遍历, 从而connect_by_root每个人的顶端的经理都是King

5、10g新特性 采用sibilings排序

作用: 因为使用order by排序会破坏层次,所以在oracle10g中,增加了siblings关键字的排序给叶子节点的关键字排序。

语法:

order siblings by <expre> asc|desc ;

它会保护层次,并且在每个等级中按expre排序

注意: order siblings by 必须紧跟着connect by,所以不能再用order by 了

例子:用order by,最后的结果是严格按照salary排序的,这样把层级关系都打乱了

select t.employee_id,t.manager_id,t.first_name,t.salary, sys_connect_by_path(t.first_name, '->'), level from hr.employees t
start with manager_id is null
connect by prior employee_id = manager_id
order by salary desc;

采用sibilings排序:结果的树结构没有被打乱,且没层级的sibilings都是按照salary排序的。

select t.employee_id,t.manager_id,t.first_name,t.salary,sys_connect_by_path(t.first_name, '->'),level from hr.employees t
start with manager_id is null
connect by prior employee_id = manager_id
order siblings by salary desc;

三、与row num 生成序列记录

rownum可用level代替。

1、简单序列:

select rownum from dual connect by rownum<=4

1
2
3
4

2、生成10-14的连续数(10开始,5行数据)

select 10+(rownum-1) from dual connect by rownum<=14-10+1

3、生成a-d的四个字母

select chr(ascii('a')+(rownum-1)) from dual connect by rownum<=ascii('d')-ascii('a')+1

4、生成2011-01-05至2011-01-10的日期

select to_date('2011-01-05','yyyy-mm-dd')+(rownum-1) from dual connect by rownum<=to_date('2011-01-10','yyyy-mm-dd')-to_date('2011-01-05','yyyy-mm-dd')+1

查询当前时间往前的12周的开始时间、结束时间、第多少周

select sysdate - (to_number(to_char(sysdate - 1, 'd')) - 1) - (rownum - 1) * 7 as startDate,
sysdate + (7 - to_number(to_char(sysdate - 1, 'd'))) - (rownum - 1) * 7 as endDate,
to_number(to_char(sysdate, 'iw')) - rownum + 1 as weekIndex
from dual
connect by level<= 12;--将level改成rownum可以实现同样的效果

  • d 表示一星期中的第几天

  • iw 表示一年中的第几周

5、字符串分割,由一行变为多行。

生成a1,b1,d1序列

select substr(id,
instr(id,',',1,rownum)+1,
instr(id,',',1,rownum+1) - instr(id,',',1,rownum)-1)--根据逗号的位置进行拆分
from (select ','||'a1,b1,d1'||',' as id from dual) --前后各加一个逗号
connect by rownum<=length(id)-length(replace(id,',',''))-1

或者

select REGEXP_SUBSTR('a1,b1,d1', '[^,]+', 1, rownum) as newport
from dual connect by rownum <= REGEXP_COUNT('a1,b1,d1', '[^,]+');

6、利用with子句生成测试数据

with temp as
(select 'a' as A,'b' as B from dual
union
select 'c' as C,'d' as D from dual
)
select * from temp;

7、日期维度数据生成方法。

select  to_date('2011-01-05','yyyy-mm-dd')+(rownum-1)  as ydate_date,
to_char(to_date('2011-01-05','yyyy-mm-dd')+(rownum-1),'yyyy') as ydate_month
from dba.tab_cols where to_date('2011-01-05','yyyy-mm-dd')+(rownum-1) != to_date('2060-01-05','yyyy-mm-dd')

Oracle递归查询connect by的更多相关文章

  1. Oracle递归查询start with connect by prior

    一.基本语法 connect by递归查询基本语法是: select 1 from 表格 start with ... connect by prior id = pId start with:表示以 ...

  2. Oracle递归查询,Oracle START WITH……CONNECT BY查询

    Oracle递归查询,Oracle START WITH……CONNECT BY查询,Oracle树查询 ================================ ©Copyright 蕃薯耀 ...

  3. mysql实现ORACLE的connect by prior父子递归查询

    oracle中有connect by prior ,可以实现父子递归查询.而mysql中没有这种功能,但我们可以变通实现. 比如一个表: Table Name: tb_Tree Id | Parent ...

  4. 【转载】Oracle递归查询:使用prior实现树操作【本文出自叶德华博客】

    本文标题:Oracle递归查询:使用prior实现树操作 本文链接:http://yedward.net/?id=41 本文版权归作者所有,欢迎转载,转载请以文字链接的形式注明文章出处. Oracle ...

  5. 【2016-11-7】【坚持学习】【Day22】【Oracle 递归查询】

    直接在oracle 递归查询语句 select * from groups start with id=:DeptId connect by prior superiorid =id 往下找 sele ...

  6. Oracle递归查询与常用分析函数

    最近学习oracle的一些知识,发现自己sql还是很薄弱,需要继续学习,现在总结一下哈. (1)oracle递归查询  start with ... connect by prior ,至于是否向上查 ...

  7. oracle中 connect by prior 递归算法 -- 理解

    oracle中 connect by prior 递归算法 -- 理解 http://blog.163.com/xxciof/blog/static/7978132720095193113752/  ...

  8. 12C 连接方式和 Oracle Easy Connect Naming method

    1.12C 连接方式 PDB is not an instance, so using SID in the connection string will not work. When the dat ...

  9. oracle使用connect by进行级联查询 树型菜单

    Oracle使用connect by进行级联查询 树型菜单(转) connect by可以用于级联查询,常用于对具有树状结构的记录查询某一节点的所有子孙节点或所有祖辈节点. 来看一个示例,现假设我们拥 ...

随机推荐

  1. C++ 顺序容器(vector,list、deque,stack,queue)

    顺序容器的种类有:vector,list.deque 顺序容器适配器: stack     //先进后出   栈 queue   //先进先出   队列 priority_queue   //也优先管 ...

  2. twemproxy配置

    redis多主从,多节点,读写分离架构. nutcracker.yml的twemproxy配置 #redis_main是twemproxy所控制redis主从集群逻辑名称 redis_main: #t ...

  3. Java静态分派和动态分派

    前言 动态分派和静态分派机制是Java多态实现的原理.本文将针对这两种机制进行浅析. 静态分派 静态分派机制最典型的代码示例如下 void test() { Father father = new S ...

  4. [C++] 例题 2.7.1 用栈实现简易计算器

    目录 前置技能 栈 (stack) 中缀表达式 (InfixExp) 与后缀表达式 (PostfixExp) 需求描述 概要设计 函数详细设计 中缀转后缀 infix_to_postfix(strin ...

  5. 从零开始学Flask框架-006

    重定向和用户会话 因为刷新页面时浏览器会重新发送之前已经发送过的最后一个请求.如果这个请求是一个包含表单数据的POST 请求,刷新页面后会再次提交表单. 基于这个原因,最好别让Web 程序把POST ...

  6. Spring AOP日志实现(三)--获取访问者用户名

    通过Security获取访问者用户名: 也可以通过session来获取: 整体思路:

  7. mysql允许root远程登录

    MySQL 默认不允许远程以root进行登陆 进入mysql后 mysql>select host, user from user; +--------------------+------+ ...

  8. JS权威指南读书笔记(二)

    第四章 表达式和运算符 1 new调用构造函数的过程     a 创建一个新的空对象     b 设置空对象的_proto_指向构造函数原型prototype     c 将这个新对象当做this的值 ...

  9. Extjs 兼容IE8常见问题及解决方法

    1. 在IE8中整个页面都打不开,一般情况是: 页面组件中最后一个属性出现了逗号 没有多余的逗号,就很有可能是组件中没有设置renderTo:Ext.getBody(); 2. 页面按钮颜色失效 自定 ...

  10. FICO-清帐函数

    转载:https://www.cnblogs.com/caizjian/p/8067071.html https://blog.csdn.net/sapliumeng/article/details/ ...