Summary_Oracle 根據父節點查詢子節點(遞迴查詢)
一、語法結構
SELECT ... FROM + 表名 START WITH + 條件1CONNECT BY PRIOR + 條件2WHERE + 條件3
條件1:是根節點的限定語句,當然可以放寬限定條件,以取得多個根節點,也就是多棵樹;在連線關係中,除了可以使用列明外,還允許使用列表達式。START WITH 子句為可選項,用來標識哪個節點作為查詢樹形結構的根節點。若該子句省略,則表示所有滿足查詢條件的行作為根節點。
條件2:是連線條件,其中用PRIOR表示上一條記錄,例如CONNECT BY PRIOR STUDENT_ID = GRADE_ID,意思就是上一條記錄的STUDENT_ID是本條記錄
條件3:是過濾條件,用於對返回的記錄進行過濾。
注意:
1,CONNECT BY PRIOR是結構化查詢中用到的;
2,START WITH... CONNECT BY PRIOR...的作用,簡單來說,就是將一個樹狀結構儲存在一張表裡。
二、應用場景
START WITH... CONNECT BY PRIOR...常見的用法,是用來遍歷含有父子關係的表結構中。比如省市關係,一個省
三、MySQL實現Start With...Connect By Prior 遞迴查詢
(1)、建立表
create table treeList(
id varchar(10), -- 節點ID
name varchar(10), -- 節點名稱
pId varchar(10) -- 父ID
);
(2)、插入資料
insert into treeList values(1,'中國',null);
insert into treeList values(2,'北京',1);
insert into treeList values(3,'上海',1);
insert into treeList values(4,'深圳',1);
insert into treeList values(5,'海淀',2);
insert into treeList values(6,'朝陽',2);
insert into treeList values(7,'昌平',2);
insert into treeList values(8,'豐臺',2);
Oracle中根據父節點查詢子節點:
SELECT * FROM treeList START WITH ID IN (1) CONNECT BY PRIOR ID=PID;
(3)、建立函式 getChildList 查詢子節點(包含父節點)
CREATE FUNCTION getChildList (rootId VARCHAR(100)) -- rootId為要查詢的節點
RETURNS VARCHAR(1000)
BEGIN
DECLARE pTemp VARCHAR(1000); -- 定義兩個臨時變數
DECLARE cTemp VARCHAR(1000); -- 定義兩個臨時變數
SET pTemp = '';
SET cTemp = rootId;
WHILE cTemp is not null DO
if (pTemp = '') then
SET pTemp = cTemp;
elseif(pTemp <> '') then
SET pTemp = concat(pTemp,',',cTemp); -- 所有節點連線成字串
end if;
SELECT group_concat(id) INTO cTemp FROM treeList WHERE FIND_IN_SET(pId,cTemp)>0;
END WHILE;
RETURN pTemp;
END;
(4)、執行方法
使用我們直接利用Find_In_Set函式配合這個getChildList函式
(a)、SELECT getChildList(1) FROM dual;
(b)、SELECT * FROM treeList WHERE FIND_IN_SET(id, getChildList(1));
注意:可以巢狀使用
SELECT * FROM treeList WHERE id in(
SELECT id FROM treeList WHERE FIND_IN_SET(id, getChildList(1))
);
(c)、SELECT * FROM treeList WHERE FIND_IN_SET(id, getChildList(2));
(d)、SELECT * FROM treeList WHERE FIND_IN_SET(id, getChildList(3));
(e)、SELECT * FROM treeList WHERE FIND_IN_SET(pid, getChildList(1));
(f)、SELECT * FROM treeList WHERE FIND_IN_SET(pid, getChildList(2));
(g)、SELECT * FROM treeList WHERE FIND_IN_SET(pid, getChildList(3));
拓展:
(5)、建立函式 getParentList 查詢父節點樹
CREATE FUNCTION getParentList(rootId VARCHAR(10000))
RETURNS VARCHAR(10000) CHARSET utf8
BEGIN
DECLARE sParentList VARCHAR(10000);
DECLARE sParentTemp VARCHAR(10000);
SET sParentTemp =rootId;
WHILE sParentTemp IS NOT NULL DO
IF (sParentList IS NOT NULL) THEN
SET sParentList = CONCAT(sParentTemp,',',sParentList);
ELSE
SET sParentList = CONCAT(sParentTemp);
END IF;
SELECT GROUP_CONCAT(pid) INTO sParentTemp FROM treeList WHERE FIND_IN_SET(id,sParentTemp)>0;
END WHILE;
RETURN sParentList;
END;
(6)、建立函式 getBetweenNodes 查詢父、子節點中的節點數
CREATE FUNCTION getBetweenNodes(startNodeId VARCHAR(100), endNodeId VARCHAR(100))
RETURNS VARCHAR(10000) CHARSET utf8
BEGIN
DECLARE sBetweenNodes VARCHAR(10000);
SELECT GROUP_CONCAT(id) INTO sBetweenNodes FROM treeList
WHERE FIND_IN_SET(id, getParentNodes(endNodeId))
AND FIND_IN_SET(pid, getChildNodes(startNodeId));
RETURN sBetweenNodes;
END;