oracle中的递归查询能够使用:select .. start with .. connect by .. prior 以下将会讲述oracle中树形查询的经常使用方式。仅仅涉及到一张表。

start with: 从某个节点開始

prior: 我的那个字段优先

一. 建表语句:

-- 菜单文件夹结构表
create table tb_menu(
id number(10) not null, -- 主键id
title varchar2(50), -- 标题
parent number(10) -- parent id
) -- 父菜单
insert into tb_menu(id, title, parent) values(1, '父菜单1',null);
insert into tb_menu(id, title, parent) values(2, '父菜单2',null);
insert into tb_menu(id, title, parent) values(3, '父菜单3',null);
insert into tb_menu(id, title, parent) values(4, '父菜单4',null);
insert into tb_menu(id, title, parent) values(5, '父菜单5',null); -- 一级菜单
insert into tb_menu(id, title, parent) values(6, '一级菜单6',1);
insert into tb_menu(id, title, parent) values(7, '一级菜单7',1);
insert into tb_menu(id, title, parent) values(8, '一级菜单8',1);
insert into tb_menu(id, title, parent) values(9, '一级菜单9',2);
insert into tb_menu(id, title, parent) values(10, '一级菜单10',2);
insert into tb_menu(id, title, parent) values(11, '一级菜单11',2);
insert into tb_menu(id, title, parent) values(12, '一级菜单12',3);
insert into tb_menu(id, title, parent) values(13, '一级菜单13',3);
insert into tb_menu(id, title, parent) values(14, '一级菜单14',3);
insert into tb_menu(id, title, parent) values(15, '一级菜单15',4);
insert into tb_menu(id, title, parent) values(16, '一级菜单16',4);
insert into tb_menu(id, title, parent) values(17, '一级菜单17',4);
insert into tb_menu(id, title, parent) values(18, '一级菜单18',5);
insert into tb_menu(id, title, parent) values(19, '一级菜单19',5);
insert into tb_menu(id, title, parent) values(20, '一级菜单20',5); -- 二级菜单
insert into tb_menu(id, title, parent) values(21, '二级菜单21',6);
insert into tb_menu(id, title, parent) values(22, '二级菜单22',6);
insert into tb_menu(id, title, parent) values(23, '二级菜单23',7);
insert into tb_menu(id, title, parent) values(24, '二级菜单24',7);
insert into tb_menu(id, title, parent) values(25, '二级菜单25',8);
insert into tb_menu(id, title, parent) values(26, '二级菜单26',9);
insert into tb_menu(id, title, parent) values(27, '二级菜单27',10);
insert into tb_menu(id, title, parent) values(28, '二级菜单28',11);
insert into tb_menu(id, title, parent) values(29, '二级菜单29',12);
insert into tb_menu(id, title, parent) values(30, '二级菜单30',13);
insert into tb_menu(id, title, parent) values(31, '二级菜单31',14);
insert into tb_menu(id, title, parent) values(32, '二级菜单32',15);
insert into tb_menu(id, title, parent) values(33, '二级菜单33',16);
insert into tb_menu(id, title, parent) values(34, '二级菜单34',17);
insert into tb_menu(id, title, parent) values(35, '二级菜单35',18);
insert into tb_menu(id, title, parent) values(36, '二级菜单36',19);
insert into tb_menu(id, title, parent) values(37, '二级菜单37',20); -- 三级菜单
insert into tb_menu(id, title, parent) values(38, '三级菜单38',21);
insert into tb_menu(id, title, parent) values(39, '三级菜单39',22);
insert into tb_menu(id, title, parent) values(40, '三级菜单40',23);
insert into tb_menu(id, title, parent) values(41, '三级菜单41',24);
insert into tb_menu(id, title, parent) values(42, '三级菜单42',25);
insert into tb_menu(id, title, parent) values(43, '三级菜单43',26);
insert into tb_menu(id, title, parent) values(44, '三级菜单44',27);
insert into tb_menu(id, title, parent) values(45, '三级菜单45',28);
insert into tb_menu(id, title, parent) values(46, '三级菜单46',28);
insert into tb_menu(id, title, parent) values(47, '三级菜单47',29);
insert into tb_menu(id, title, parent) values(48, '三级菜单48',30);
insert into tb_menu(id, title, parent) values(49, '三级菜单49',31);
insert into tb_menu(id, title, parent) values(50, '三级菜单50',31);
commit; select * from tb_menu;

parent字段为上级id,假设是顶级父节点,那么该parent为null

二. 树操作

我们从最主要的操作,逐步列出树查询中常见的操作。全部查询出来的节点以家族中的辈份作例如。

1)、查找树中的全部顶级父节点(辈份最大的人)。如果这个树是个文件夹结构,那么第一个操作总是找出全部的顶级节点,再依据该节点找到其下属节点。

select * from tb_menu m where m.parent is null;

2)、查找一个节点的直属子节点(全部儿子)。

假设查找的是直属子类节点,也是不用用到树型查询的。

select * from tb_menu m where m.parent=1;

3)、查找一个节点的全部直属子节点(全部后代)。

select * from tb_menu m start with m.id=1 connect by m.parent=prior m.id;

这个查找的是id为1的节点下的全部直属子类节点,包含子辈的和孙子辈的全部直属节点。

4)、查找一个节点的直属父节点(父亲)。 假设查找的是节点的直属父节点。也是不用用到树型查询的。

-- c: child, p: parent
select c.id, c.title, p.id parent_id, p.title parent_title
from tb_menu c, tb_menu p
where c.parent=p.id and c.id=6

5)、查找一个节点的全部直属父节点(祖宗)。

select * from tb_menu m
start with m.id=38
connect by prior m.parent=m.id;

这里查找的就是id为1的全部直属父节点。打个例如就是找到一个人的父亲、祖父等。

可是值得注意的是这个查询出来的结果的顺序是先列出子类节点再列出父类节点。

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

上面列出两个树型查询方式。第3条语句和第5条语句,这两条语句之间的差别在于priorkeyword的位置不同,所以决定了查询的方式不同。 当parent

= prior id时,数据库会依据当前的id迭代出parent与该id同样的记录。所以查询的结果是迭代出了全部的子类记录;而prior parent = id时,数据库会

跟据当前的parent来迭代出与当前的parent同样的id的记录。所以查询出来的结果就是全部的父类结果。

记忆方式:prior即优先的意思,

parent = prior
id表示我的id字段和别人的parent字段相等。即递归子孙

prior parent = id表示我的parent字段和别人的id字段相等,即递归祖先

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

6)、查询一个节点的兄弟节点(亲兄弟)。

-- m.parent=m2.parent 同一个父亲
select * from tb_menu m1
where exists
(select *
from tb_menu m2
where m1.parent=m2.parent
and m2.id=6)

7)、查询与一个节点同级的节点(族兄弟)。

假设在表中设置了级别的字段,那么在做这类查询时会非常轻松,同一级别的就是与那个节点同级的,在这里列出不使用该字段时的实现!

with tmp as(
select a.*, level leaf
from tb_menu a
start with a.parent is null
connect by a.parent = prior a.id
)
select *
from tmp
where leaf = (select leaf from tmp where id = 50);

这里使用两个技巧,一个是使用了level来标识每一个节点在表中的级别,还有就是使用with语法模拟出了一张带有级别的暂时表。

8)、查询一个节点的父节点的的兄弟节点(伯父与叔父)。

with tmp as(
select tb_menu.*, level lev
from tb_menu
start with parent is null
connect by parent = prior id
)
select b.*
from tmp b,(select *
from tmp
where id = 21 and lev = 2) a
where b.lev = 1
union all
select *
from tmp
where parent = (select distinct x.id
from tmp x, --祖父
tmp y, --父亲
(select *
from tmp
where id = 21 and lev > 2) z --儿子
where y.id = z.parent and x.id = y.parent);

这里查询分成下面几步。

首先,和第7个一样,将全表都使用暂时表加上级别。

其次,依据级别来推断有几种类型,以上文中举的样例来说。有三种情况:

(1)当前节点为顶级节点,即查询出来的lev值为1,那么它没有上级节点,不予考虑。

(2)当前节点为2级节点,查询出来的lev值为2,那么就仅仅要保证lev级别为1的就是其上级节点的兄弟节点。

(3)其他情况就是3以及以上级别。那么就要先查询出其上级的上级节点(祖父)。再来推断祖父的下级节点都是属于该节点的上级节点的兄弟节点。

最后,就是使用union将查询出来的结果进行结合起来,形成结果集。

9)、查询一个节点的父节点的同级节点(族叔)。

这个事实上跟第7种情况是同样的。

with tmp as(
select a.*, level leaf
from tb_menu a
start with a.parent is null
connect by a.parent = prior a.id
)
select *
from tmp
where leaf = (select leaf from tmp where id = 6) - 1;

基本上,常见的查询在里面了,不常见的也有部分了。当中。查询的内容都是节点的基本信息。都是数据表中的基本字段,可是在树查询中还有些特殊

需求,是对查询数据进行了处理的。常见的包含列出树路径等。

10)、列出名称所有路径。

这里常见的有两种情况,一种是从顶级列出,直到当前节点的名称(或者其他属性);一种是从当前节点列出,直到顶级节点的名称(或其他属性)

举地址为例:国内的习惯是从省開始、到市、到县、到居委会的。而国外的习惯正好相反。

从顶部開始:

select sys_connect_by_path (title, '/')
from tb_menu
where id = 50
start with parent is null
connect by parent = prior id;

从当前节点開始:

select sys_connect_by_path (title, '/')
from tb_menu
start with id = 50
connect by prior parent = id;

第一个sql是从根节点開始遍历,而第二个sql是直接找到当前节点。从效率上来说已经是千差万别。更关键的是第一个sql仅仅能选择一个节点,而第二个sql却是遍历出了一颗树来。

sys_connect_by_path函数就是从start with開始的地方開始遍历。并记下其遍历到的节点。start with開始的地方被视为根节点。将遍历到的路径依据函数中的分隔符,组成一个新的字符串。这个功能还是非常强大的。

11)、列出当前节点的根节点。在前面说过,根节点就是start with開始的地方。

select connect_by_root title, tb_menu.*
from tb_menu
start with id = 50
connect by prior parent = id;

connect_by_root函数用在列的前面,记录的是当前节点的根节点的内容。

12)、列出当前节点是否为叶子。这个比較常见,尤其在动态文件夹中。在查出的内容是否还有下级节点时,这个函数是非常适用的。

select connect_by_isleaf, tb_menu.*
from tb_menu
start with parent is null
connect by parent = prior id;

connect_by_isleaf函数用来推断当前节点是否包括下级节点,假设包括的话,说明不是叶子节点。这里返回0;反之。假设不包括下级节点。返回1。

摘自: http://www.cnblogs.com/linjiqin/archive/2013/06/24/3152674.html

oracle树操作(select .. start with .. connect by .. prior)的更多相关文章

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

    转自http://www.cnblogs.com/linjiqin/archive/2013/06/24/3152674.html Oracle 树操作(select-start with-conne ...

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

    摘自:http://www.cnblogs.com/linjiqin/archive/2013/06/24/3152674.html oracle树查询的最重要的就是select…start with ...

  3. oracle树操作(select start with connect by prior)

    oracle中的递归查询可以使用:select .. start with .. connect by .. prior 下面将会讲述oracle中树形查询的常用方式,只涉及到一张表. 一. 建表语句 ...

  4. Oracle学习之Oracle 树操作(select…start with…connect by…prior)

    转自:http://www.cnblogs.com/linjiqin/archive/2013/06/24/3152674.html oracle树查询的最重要的就是select…start with ...

  5. (转载)Oracle 树操作(select…start with…connect by…prior)

    转载地址:https://www.cnblogs.com/linjiqin/p/3152674.html 备注:如有侵权,请立即联系删除. oracle树查询的最重要的就是select…start w ...

  6. [转]Oracle 树操作(select…start with…connect by…prior)

    原文地址:https://www.cnblogs.com/colder/p/4838574.html oracle树查询的最重要的就是select…start with…connect by…prio ...

  7. IT该忍者神龟Oracle 树操作(select…start with…connect by…prior)

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

  8. Oracle 树操作(select…start with…connect by…prior)---转

    原文地址:http://www.cnblogs.com/linjiqin/p/3152674.html -----------

  9. Oracle树查询,start with connect by prior 递归查询用法(转载)

    本人觉得这个写的真不错,实用性强,就转载过来了 这个子句主要是用于B树结构类型的数据递归查询,给出B树结构类型中的任意一个结点,遍历其最终父结点或者子结点. 先看原始数据: 1 create tabl ...

  10. Oracle 树操作

    Oracle 树操作(select…start with…connect by…prior) oracle树查询的最重要的就是select…start with…connect by…prior语法了 ...

随机推荐

  1. CSLA框架的codesmith模板改造

    一直有关注CSLA框架,最近闲来无事,折腾了下,在最新的r3054版本基础上修改了一些东西,以备自己用,有兴趣的园友可以下载共同研究 1.添加了默认的授权规则 如果是列表对象则生成列表权限,User的 ...

  2. Winserver服务器-AD字段对照简图

    AD字段对照简图

  3. bzoj3262: 陌上花开(cdq分治+树状数组)

    3262: 陌上花开 题目:传送门 题解: %%%cdq分治 很强大的一个暴力...感觉比分块高级多了 这道题目就是一个十分经典的三维偏序的例题: 一维直接暴力排序x 二维用csq维护y 三维用树状数 ...

  4. 前后端分离跨域 关于前后端分离开发环境下的跨域访问问题(angular proxy=>nginx )

    前后端分离后遇到了跨域访问的问题: angular1中使用proxy很麻烦,最后还是失败结束:最后总结3种方法如下: 本人使用的第一种方法,只是开发环境下使用很方便! 1:禁掉谷歌的安全策略(Turn ...

  5. Defining and using constants from PySide in QML

    Defining and using constants from PySide in QML This PySide tutorial shows you how to define constan ...

  6. 使用Swing组件编写一个支持中文文本编辑程序ChineseTextEdit.java

      import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.io.*; public class C ...

  7. Kettle的概念学习系列之Kettle是什么?(一)

    不多说,直接上干货! Kettle是什么? Kettle是一款国外开源的ETL工具,纯java编写,可以在Window.Linux.Unix上运行,绿色无需安装,数据抽取高效稳定. Kettle 中文 ...

  8. 线上服务CPU100%问题快速定位实战--转

    来自微信公众号 架构师之路 功能问题,通过日志,单步调试相对比较好定位. 性能问题,例如线上服务器CPU100%,如何找到相关服务,如何定位问题代码,更考验技术人的功底. 58到家架构部,运维部,58 ...

  9. [转]Adobe CC 2018 下载链接 Creative Cloud 2018 - Creative Cloud 2018 – Adobe CC 2018 Download Links

    Creative Cloud 2018 – Adobe CC 2018 Download Links – ALL Languages Adobe CC 2018Direct Downloads Win ...

  10. CSS中元素各种居中方法(思维导图)

    前言 用思维导图的方式简单总结一下各种元素的居中方法,如下图: 补充一下: table自带功能 100% 高度的 afrer before 加上 inline block优化 div 装成 table ...