oracle中的树状查询
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中的树状查询的更多相关文章
- oracle 树状查询
做树状查询的时候,oracle有自己的优势,一条sql语句就可以搞定,而mysql这种数据库就只能用递归了... 递归的项目实例: //递归取到栏目路径 public List getTreeList ...
- Oracle 中利用闪回查询确定某表在某时间点之后的修改内容,并恢复至该时间点
Oracle 中利用闪回查询确定某表在某时间点之后的修改内容: 1.查看 DELETE 及 UPDATE 操作修改的数据: SQL> SELECT * FROM tab AS OF TIMEST ...
- GTK+中的树状列表构件(GtkTreeView)
GTK+中的树状列表构件(GtkTreeView) GTK+中的树状列表构件(GtkTreeView) 在本章的GTK+程序设计教程中,我们将向大家重点介绍非常常用也有点复杂的构件--GtkTreeV ...
- Oracle中的SQL分页查询原理和方法详解
Oracle中的SQL分页查询原理和方法详解 分析得不错! http://blog.csdn.net/anxpp/article/details/51534006
- oracle存储过程删除树状结构的表数据
今天在删除一个车辆品牌表的时候,遇到了一个问题,是在java的代码中做逻辑删除还是直接在Oracle中一次删除完成呢 思来想去觉得还是在sql里直接删除比较合适, 为什么呢? 第一,涉及数据库的读写操 ...
- mysql中递归树状结构<转>
在Oracle 中我们知道有一个 Hierarchical Queries 通过CONNECT BY 我们可以方便的查了所有当前节点下的所有子节点.但很遗憾,在MySQL的目前版本中还没有对应的功能. ...
- Android中的树状(tree)列表
树状列表前端挺常用的,还有人专门写过Ztree,Android中有的时候也需要使用到树状列表,上篇文章写了一下ExpandableListView,ExpandableListView最多支持两级结构 ...
- php中构建树状图
/** * 指定根层级的树状图 * @param array $list 初始数组 * @param int $root 最上级一条数据的id * @param string $pk 每一条数据的id ...
- 在SqlServer中通过SQL语句实现树状查询
CREATE PROCEDURE [dbo].[GetTree] @Id int AS BEGIN with cte as ( as lvl from Entity where Id = @Id un ...
随机推荐
- python 之 软件开发目录规范 、logging模块
6.4 软件开发目录规范 软件(例如:ATM)目录应该包含: 文件名 存放 备注 bin start.py,用于起动程序 core src.py,程序核心功能代码 conf settings. ...
- gitlab之source tree使用方法
一.简介 1.source tree 是什么 可视化项目版本控制软件,使用git项目管理,支持windows/mac 客户端使用source tree开发源码,图形化提交到gitlab 二.使用sou ...
- Sublime Text 3 配置 sass
先安装Sublime Text的sass 和 sass build插件, Sublime Text新建一个test.scss文件 $color: #369; body { backgroun ...
- 洛谷P3831 回家的路
题目背景 SHOI2012 D2T1 题目描述 \(2046\) 年 \(OI\) 城的城市轨道交通建设终于全部竣工,由于前期规划周密,建成后的轨道交通网络由\(2n\)条地铁线路构成,组成了一个\( ...
- redis之安装
redis之安装 redis redis介绍 redis是一个key-value存储系统,菲关系型数据库.和Memcached类似,他支持存储的value类型相对更多,包括字符串.列表.哈希散列表.集 ...
- 数组Array的相关操作。
一 数组的对象(元素): 1. 数字, 2 .字符串 3 变量 4. 函数 .... 二 数组的创建 1 var arrayObj = new Array(); var a =new Array(si ...
- Educational Codeforces Round 66 (Rated for Div. 2) B. Catch Overflow!
链接:https://codeforces.com/contest/1175/problem/B 题意: You are given a function ff written in some bas ...
- HDU1409 Is It a Number
http://acm.hdu.edu.cn/showproblem.php?pid=1409 没啥好说的,至今也不知道到底错在哪里了,看了discuss才过的 #include <iostrea ...
- 070 Climbing Stairs
你正在爬楼梯.需要 n 步你才能到达顶部.每次你可以爬 1 或 2 个台阶.你有多少种不同的方式可以爬到楼顶呢?注意:给定 n 将是一个正整数.示例 1:输入: 2输出: 2说明: 有两种方法可以爬到 ...
- MySQL存储过程多条修改语句
DROP procedure Sel_Function_ActivityPastDueDELIMITER $$DROP procedure IF EXISTS`shouyi`.`Sel_Functio ...