1. 程式人生 > >Summary_Oracle 根據父節點查詢子節點(遞迴查詢)

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是本條記錄

的GRADE_ID,即本記錄的父親是上一條記錄。CONNECT BY子句說明每行資料將是按照層次順序檢索,並規定將表中的資料連入樹形結構的關係中。PRIOR運算子必須放置在連線關係的2列中某一個的前面。對於節點間的父子關係,PRIOR運算子在一側表示父節點,在另一側表示子節點,從而確定查找樹結構的順序是自頂向下,還是自底向上。

條件3:是過濾條件,用於對返回的記錄進行過濾。

注意:

1,CONNECT BY PRIOR是結構化查詢中用到的;

2,START WITH... CONNECT BY PRIOR...的作用,簡單來說,就是將一個樹狀結構儲存在一張表裡。

二、應用場景

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;