2012-10-09 88 views
3

找到葉子,我知道這樣的問題已經張貼在這裏很多次,〔實施例:Java wayMySQL的:如何在特定的節點

我在標準樹模式(idparent_id大量的數據(150K +), some_data

問題:如何獲得給定node_id的葉子?

表結構:

CREATE TABLE `DATA_TREE` (
    `ID` int(11) NOT NULL, 
    `PARENT_ID` int(11) NOT NULL, 
    `DATA` varchar(45) DEFAULT NULL, 
    PRIMARY KEY (`ID`), 
    UNIQUE KEY `ID_UNIQUE` (`ID`), 
    KEY `fk_DATA_TREE_1_idx` (`PARENT_ID`), 
    CONSTRAINT `fk_DATA_TREE_1` FOREIGN KEY (`PARENT_ID`) REFERENCES `DATA_TREE` (`ID`) ON DELETE NO ACTION ON UPDATE NO ACTION 
) ENGINE=InnoDB DEFAULT CHARSET=utf 

數據庫:MySQL 5.1.61

+1

指這樣的: http://stackoverflow.com/questions/169817/is-it-possible-to-query -a-tree-structure-table-in-mysql-in-a-single-query-to-an – AnandPhadke

+0

@AnandPhadke +1 thx很多 – WBAR

+1

我想重新打開這個問題,因爲我想要獎勵'guru_florida'50分努力!這個解決方案真的幫了我和工作! – WBAR

回答

6

有沒有辦法在單個查詢做到這一點。即使有,它可能會非常低效。

我們可以通過存儲過程和循環來完成。你添加的索引應該很快。這使用兩個表從輸入表(A)中選擇節點並將節點及其子節點插入(B)。然後它將B交換爲A,並重復,直到A中不再存在非葉節點爲止。好的一點是循環迭代只有它們在輸入節點和最後一個葉節點之間的層數一樣多,在大多數情況下可能不那麼深。這個存儲過程比在代碼中進行外部操作要快。

僅供參考我在安裝處理臨時表時遇到困難,如果出現'錯誤2',請刪除臨時關鍵字。

delimiter $$ 
drop procedure if exists GetLeafNodes $$ 
create procedure GetLeafNodes(nodeid int) 
begin 
declare N int default 1; 

-- create two working sets of IDs, we'll go back and forth between these two sets 
drop temporary table if exists A; 
drop temporary table if exists B; 
create temporary table A(node int, child int); 
create temporary table B(node int, child int); 

-- insert our single input node into the working set 
insert into A values (null, nodeid); 

while (N>0) do 
    -- keep selecting child nodes for each node we are now tracking 
    -- leaf nodes will end up with the child set to null 
    insert into B 
    select ifnull(A.child,A.node), tree.ID 
    from A 
    left outer join DATA_TREE as tree on A.child=tree.parent_id; 

    -- now swap A and B 
    rename table A to temp, B to A, temp to B; 

    -- remove non-leaf nodes from table B 
    delete from B; 

    -- exit when there are no longer any non-leaf nodes in A 
    set N=(select count(*) from A where child is not null); 
end while; 

-- now output our list of leaf nodes 
select node from A; 

drop temporary table A; 
drop temporary table B; 
end $$ 
DELIMITER ; 
call GetLeafNodes(4); 

我用下面的樣本集來進行測試:

CREATE TABLE `DATA_TREE` (
    `ID` int(11) NOT NULL, 
    `PARENT_ID` int(11) NOT NULL, 
    PRIMARY KEY (`ID`), 
    UNIQUE KEY `ID_UNIQUE` (`ID`), 
    KEY `fk_DATA_TREE_1_idx` (`PARENT_ID`) 
) ENGINE=InnoDB 
; 

insert into DATA_TREE values 
(1,0),(2,1),(3,1),(4,1),(5,3),(6,3),(7,4),(8,4),(9,4),(10,6),(11,6),(12,7),(13,9),(14,9),(15,12),(16,12),(17,12),(18,14); 
+0

+1太棒了!這很重要:D – WBAR

相關問題