1. 程式人生 > >oracle中的樹狀查詢

oracle中的樹狀查詢

節點 pctfree con 返回 date 產生 技術 mage 直接

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中的樹狀查詢