oracle中的树状查询

工作中经常会遇到将数据库中的数据以树的形式展现的需求。以下我们来看一下该需求在Oracle中如何实现。

首先我们需要有一个树形的表结构(当然有时候会出现表结构不是典型的树形结构,而是多表存储,需要根据多表连接查询生成树)

一、树型表结构:
节点ID  上级ID  节点名称

二、用法: 
select 节点ID,节点名称,level
from 表名
connect by prior 节点ID=上级节点ID
start with 上级节点ID=节点值

说明:
1、常见的树形结构为公司组织机构、地区……
2、求节点ID以上的结构,或以下的结构,将“节点ID=上级节点ID”左右顺序换一下即可。
3、Level为Oracle的特殊字段,表示“层”的意思。当前节点ID的下一层节点为“1”。

测试SQL: 1,建立表结构

CREATE TABLE "TEAMB0"."MATBOM"

( "FACT_NO" CHAR(4) NOT NULL ENABLE,
"CARRY_MK" CHAR(1) NOT NULL ENABLE,
"MAIN_MAT_NO" CHAR(20) NOT NULL ENABLE,
"SUB_MAT_NO" CHAR(20) NOT NULL ENABLE,
"PRD_CODE" CHAR(1) NOT NULL ENABLE,
"PRD_RATE" NUMBER(8,5) NOT NULL ENABLE,
"MODIFY_USER" VARCHAR2(60),
"MODIFY_DATE" CHAR(14),
"BLOC_MK" CHAR(1)
) PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING
STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)
TABLESPACE "USER_DATA"

 插入数据:

Insert into MATBOM (FACT_NO,CARRY_MK,MAIN_MAT_NO,SUB_MAT_NO,PRD_CODE,PRD_RATE,MODIFY_USER,MODIFY_DATE,BLOC_MK) values ('216M','N','A020408G02A059 ','A020408G01A059 ','3',1,null,null,null);
Insert into MATBOM (FACT_NO,CARRY_MK,MAIN_MAT_NO,SUB_MAT_NO,PRD_CODE,PRD_RATE,MODIFY_USER,MODIFY_DATE,BLOC_MK) values ('216M','N','A020408G15A059 ','A020408G01A059 ','3',1,null,null,null);
Insert into MATBOM (FACT_NO,CARRY_MK,MAIN_MAT_NO,SUB_MAT_NO,PRD_CODE,PRD_RATE,MODIFY_USER,MODIFY_DATE,BLOC_MK) values ('216M','N','A020408G18A059 ','A020408G01A059 ','5',1,'S6042382','20081020133712',null);
Insert into MATBOM (FACT_NO,CARRY_MK,MAIN_MAT_NO,SUB_MAT_NO,PRD_CODE,PRD_RATE,MODIFY_USER,MODIFY_DATE,BLOC_MK) values ('216M','N','N090823G09A059 ','A020408G01A059 ','1',1,'S6042382','20081208150154',null);
Insert into MATBOM (FACT_NO,CARRY_MK,MAIN_MAT_NO,SUB_MAT_NO,PRD_CODE,PRD_RATE,MODIFY_USER,MODIFY_DATE,BLOC_MK) values ('216M','N','A020408G01A059 ','A020408G01A059-1 ','3',1,null,null,null);
INSERT INTO MATBOM (FACT_NO,CARRY_MK,MAIN_MAT_NO,SUB_MAT_NO,PRD_CODE,PRD_RATE,MODIFY_USER,MODIFY_DATE,BLOC_MK) VALUES ('216M','N','A020408G01A059 ','A020408G01A059-2 ','3',1,NULL,NULL,NULL);

INSERT INTO MATBOM (FACT_NO,CARRY_MK,MAIN_MAT_NO,SUB_MAT_NO,PRD_CODE,PRD_RATE,MODIFY_USER,MODIFY_DATE,BLOC_MK)
VALUES ('216M','N','T1-A020408G02A059 ','A020408G02A059 ','3',1,NULL,NULL,NULL);

SQL查询

--prior放的左右位置决定了检索是自底向上还是自顶向下. 左边是自上而下(找子节点),右边是自下而上(找父节点)
--找父节点

SELECT MAIN_MAT_NO,sub_mat_no,level
FROM MATBOM
CONNECT BY SUB_MAT_NO = PRIOR MAIN_MAT_NO
START WITH SUB_MAT_NO = 'A020408G01A059 ';

;or

SELECT MAIN_MAT_NO,sub_mat_no,level
FROM MATBOM

START WITH SUB_MAT_NO = 'A020408G01A059 '
CONNECT BY SUB_MAT_NO = PRIOR MAIN_MAT_NO;

;

--找子节点节点
-- (子节点)SUB_MAT_NO 为A020408G01A059 的子材料,以及A020408G01A059 子材料下的所有直接或间接子材料(prior 在左边, prior、MAIN_MAT_NO(等号右边)在右边)

SELECT MAIN_MAT_NO,sub_mat_no,level
FROM MATBOM
START WITH SUB_MAT_NO = 'A020408G01A059'
CONNECT BY PRIOR SUB_MAT_NO = MAIN_MAT_NO;

三、性能问题  

  对于 start with connect by语句的执行,oracle会进行递归查询,当数据量大的时候会产生性能相关问题。

--生成执行计划
EXPLAIN PLAN FOR SELECT * FROM MATBOM START WITH SUB_MAT_NO = 'A020408G01A059' CONNECT BY SUB_MAT_NO = PRIOR MAIN_MAT_NO;

-- 查询执行计划
select * from table( dbms_xplan.display);

语句执行计划结果如下:

Plan hash value: 1868394721

--------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 7 | 840 | 3 (0)| 00:00:01 |
|* 1 | CONNECT BY NO FILTERING WITH START-WITH| | | | | |
| 2 | TABLE ACCESS FULL | MATBOM | 7 | 840 | 3 (0)| 00:00:01 |
--------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

1 - access("SUB_MAT_NO"=PRIOR "MAIN_MAT_NO")
filter("SUB_MAT_NO"='A020408G01A059')

Note
-----
- dynamic sampling used for this statement

通过该执行计划得知,改语句执行了7步操作,才将结果集查询并返回。当需要查询条件进行过滤的时候,我们可以通过查看执行计划从而对sql进行优化。
												

oracle中的树状查询的更多相关文章

  1. oracle 树状查询

    做树状查询的时候,oracle有自己的优势,一条sql语句就可以搞定,而mysql这种数据库就只能用递归了... 递归的项目实例: //递归取到栏目路径 public List getTreeList ...

  2. Oracle 中利用闪回查询确定某表在某时间点之后的修改内容,并恢复至该时间点

    Oracle 中利用闪回查询确定某表在某时间点之后的修改内容: 1.查看 DELETE 及 UPDATE 操作修改的数据: SQL> SELECT * FROM tab AS OF TIMEST ...

  3. GTK+中的树状列表构件(GtkTreeView)

    GTK+中的树状列表构件(GtkTreeView) GTK+中的树状列表构件(GtkTreeView) 在本章的GTK+程序设计教程中,我们将向大家重点介绍非常常用也有点复杂的构件--GtkTreeV ...

  4. Oracle中的SQL分页查询原理和方法详解

    Oracle中的SQL分页查询原理和方法详解 分析得不错! http://blog.csdn.net/anxpp/article/details/51534006

  5. oracle存储过程删除树状结构的表数据

    今天在删除一个车辆品牌表的时候,遇到了一个问题,是在java的代码中做逻辑删除还是直接在Oracle中一次删除完成呢 思来想去觉得还是在sql里直接删除比较合适, 为什么呢? 第一,涉及数据库的读写操 ...

  6. mysql中递归树状结构<转>

    在Oracle 中我们知道有一个 Hierarchical Queries 通过CONNECT BY 我们可以方便的查了所有当前节点下的所有子节点.但很遗憾,在MySQL的目前版本中还没有对应的功能. ...

  7. Android中的树状(tree)列表

    树状列表前端挺常用的,还有人专门写过Ztree,Android中有的时候也需要使用到树状列表,上篇文章写了一下ExpandableListView,ExpandableListView最多支持两级结构 ...

  8. php中构建树状图

    /** * 指定根层级的树状图 * @param array $list 初始数组 * @param int $root 最上级一条数据的id * @param string $pk 每一条数据的id ...

  9. 在SqlServer中通过SQL语句实现树状查询

    CREATE PROCEDURE [dbo].[GetTree] @Id int AS BEGIN with cte as ( as lvl from Entity where Id = @Id un ...

随机推荐

  1. loj #6079. 「2017 山东一轮集训 Day7」养猫【最大费用最大流】

    首先假设全睡觉,然后用费用流考虑平衡要求建立网络流 把1~n的点看作是i-k+1~k这一段的和,连接(i,i+k,1,e[i]-s[i]),表示把i改成吃饭,能对i~i+k-1这一段的点产生影响:然后 ...

  2. 洛谷P1220 关路灯(区间dp)

    关路灯 某一村庄在一条路线上安装了n盏路灯,每盏灯的功率有大有小(即同一段时间内消耗的电量有多有少).老张就住在这条路中间某一路灯旁,他有一项工作就是每天早上天亮时一盏一盏地关掉这些路灯.为了给村里节 ...

  3. gui - tkinter 开发

    GUI 用户交互界面 tkinter 介绍 tkinter python自带的gui库,对图形图像处理库tk的封装 其他gui:pythonwin,wxpython,pyQT.. 概念介绍 组件:组成 ...

  4. Python面向对象之单例模式

    单例模式(Singleton Pattern)是一种常用的软件设计模式,该模式的主要目的是确保某 一个类只有一个实例存在.当你希望在整个系统中,某个类只能出现一个实例时,单例对象就 能派上用场. 单例 ...

  5. Prime Count 求大区间素数个数

    http://acm.gdufe.edu.cn/Problem/read/id/1333 https://www.zhihu.com/question/29580448/answer/44874605

  6. Windows1

    ① 对Windows的设置一般在, 所有设置, 控制面板(control), 管理方式打开此电脑和此电脑上的选项 ② 关闭对账号安全的检验, 在控制面板中, 找到系统和安全, 再找到更改用户账号控制设 ...

  7. nodejs 实践:express 最佳实践(二) 中间件

    express 最佳实践(二):中间件 第一篇 express 最佳实践(一):项目结构 express 中最重要的就是中间件了,可以说中间件组成了express,中间件就是 express 的核心. ...

  8. @ConfigurationProperties

    功能 将属性文件与一个Java类绑定,属性文件中的变量与Java类中的成员变量一一对应,无需完全一致. 如需将 @ConfigurationProperties 注解的目标类添加到Spring IOC ...

  9. Java程序运行参数

    Java主函数形式:public static void main(String[] args){......} 也就是说可以向Java程序传递一个String[]. 1.在IDEA中debug.ru ...

  10. storm中的topology-worker-executor-task

    调度角色 调度方法 自定义调度 1 调度角色   任务角色结构 上图是JStorm中一个topology对应的任务执行结构,其中worker是进程,executor对应于线程,task对应着spout ...