Oracle层次查询及应用(start with connect by)
来源:互联网 发布:手机分贝测试软件 编辑:程序博客网 时间:2024/05/16 12:29
摘要:本文将根据对层次查询语句简单例子的说明来理解应用,并举例实际的应用案例。
========================================================================================================
start with connect by 层次查询(Hierarchical Queries)
========================================================================================================
语法:
--------------------------------------------------------------------------------------------------------
SELECT *
SELECT
START WITH ID = 1
CONNECT BY PRIOR PID = ID
start with: 表示根记录的条件
connect by: 指定了父记录行和子记录行之间的关系,在层次查询中,条件表达式必须使用prior操作符来指定父记录行
如:
CONNECT BY PRIOR pid = id 或者CONNECT BY pid = PRIOR id
如果connect by 条件是一个组合条件,那么只有一个条件需要prior操作符,
如:
CONNECT BY last_name != 'King' AND PRIOR employee_id = manager_id
不过,connect by 不能包含子查询。
prior是一个二元操作符,最常见的是用于列值相等的比较,它让Oracle使用对应列的父亲行的值。使用非相等比较,极有可能倒致查询陷入无穷循环,以出错终止。
举例:
========================================================================================================
Start with...Connect By子句递归查询一般用于一个表维护树形结构的应用。可以通过一个简单的例子来理解其使用的概念和方法。
创建示例表:
--------------------------------------------------------------------------------------------------------
CREATE TABLE tbl_test
(
);
插入测试数据:
--------------------------------------------------------------------------------------------------------
INSERT INTO TBL_TEST(ID,NAME,PID) VALUES('1','111','0');
INSERT INTO TBL_TEST(ID,NAME,PID) VALUES('2','222','1');
INSERT INTO TBL_TEST(ID,NAME,PID) VALUES('3','333','0');
INSERT INTO TBL_TEST(ID,NAME,PID) VALUES('4','444','1');
INSERT INTO TBL_TEST(ID,NAME,PID) VALUES('5','555','2');
INSERT INTO TBL_TEST(ID,NAME,PID) VALUES('6','666','0');
INSERT INTO TBL_TEST(ID,NAME,PID) VALUES('9','999','2');
全部记录
--------------------------------------------------------------------------------------------------------
SELECT * FROM tbl_test
如下记录
--------------------
ID
1
2
3
4
5
6
9
从父记录行向子记录行递归
--------------------------------------------------------------------------------------------------------
SELECT
START WITH ID = 1
CONNECT BY PRIOR ID = pid
如下记录
--------------------
ID
1
2
5
9
4
--------------------
解析:
1.(START WITH ID = 1)根记录条件为ID=1
2.(CONNECT BY PRIOR ID = pid):由列ID与PID建立父子关系并进行比较,从ID为1开始,在PID列中寻找为1的行,可以找到ID为2和4,再将ID为2和4从PID中再寻找,又可以找到5和9,以上结果因此而来。
从子记录向父记录递归
--------------------------------------------------------------------------------------------------------
SELECT
START WITH ID = 5
CONNECT BY PRIOR pid = ID
如下记录
--------------------
ID
5
2
1
--------------------
解析:
1.(START WITH ID = 5)根记录条件为ID=5
2.(CONNECT BY PRIOR pid = ID):以之上查询恰相反,其中的取值也正相反。ID为5的PID列的值为2,因PRIOR在PID列一边,确从PID列中取值,在PID列取值2向ID 列进行递归查询,在ID列中找到2的值,再确认其对应的PID为1,再次取值1在ID中找到结果,最终共计三条记录。
========================================================================================================
LEVEL,ROW_NUMBER,OVER的应用
========================================================================================================
设PID为父值,并根据PID进行分组及确定LEVEL
--------------------------------------------------------------------------------------------------------
SELECT
START WITH pid = 0
CONNECT BY PRIOR ID = pid
如下记录
--------------------------------------------------------------------------------------------------------
LEVEL
1
1
1
2
2
3
3
根据父值逐层区分
--------------------------------------------------------------------------------------------------------
SELECT
START WITH pid = 0
CONNECT BY pid = PRIOR ID
记录如下:
--------------------------------------------------------------------------------------------------------
PID
0
1
2
2
1
0
0
可以清楚看出,ID为1,其子值为2和4(level 2),而2值又有子值5、9(level 3),3、6无子值存在。
========================================================================================================
SYS_CONNECT_BY_PATH 函数
========================================================================================================
以上例显示看出,PID分为三个分支,NAME分别如下:
第一分支:111,333,666
第二分支:222,444
第三分支:555,999
脚本:
--------------------------------------------------------------------------------------------------------
SELECT
START WITH by_pid = 1
CONNECT BY rn - 1 = PRIOR rn
记录结果:
--------------------------------------------------------------------------------------------------------
PID
0
0
0
1
1
2
2
如取单值列,可取其中最大值,使用MAX,然后应用GROUP BY即可,如下脚本:
--------------------------------------------------------------------------------------------------------
SELECT
START WITH by_pid = 1
CONNECT BY rn - 1 = PRIOR rn
记录结果:
--------------------------------------------------------------------------------------------------------
PID
0
1
2
--------------------------------------------------------------------------------------------------------
常用于行列转换的应用。
应用:
一、ERP BOM(物料清单)
========================================================================================================
SELECT DISTINCT b.lvl lv, msi1.segment1 p_item, msi1.description p_item_desc,