2012-04-27 10 views
2

私は隣接リストモデルを使用して、(非常に動的な)ツリー構造をMySQLデータベースに格納しています。できれば、ストアドルーチンへの単一の呼び出しを介して、特定のノードのすべての子孫を選択する方法が必要です。ネストされたセットモデルはこれを簡単にしますが、他のものは非常に困難になるので、残念ながらそれは私の選択肢ではありません。ここで私はこれまで持っているものです:ツリーノードのすべての子孫を選択

DELIMITER // 

CREATE PROCEDURE get_descendants(node_id INT) 
    BEGIN 

    DROP TEMPORARY TABLE IF EXISTS descendants; 
    CREATE TEMPORARY TABLE descendants (id INT, name VARCHAR(100), parent_id INT); 

    INSERT INTO descendants 
     SELECT * 
     FROM nodes 
     WHERE parent_id <=> node_id; 

    -- ...? 

    END// 

DELIMITER ; 

アイデアは、私は葉に到達するまでドリルダウンし、子孫のテーブルに子を追加するに保つことです。私はプロシージャの外から一時テーブルにアクセスすることができます...私は願っています。 (実際には、格納された関数から結果セットを返すことができないのは残念です。)

どういうわけか、結果をループして各行に対して新しいSELECT文を発行する必要があります。カーソルがここで役立つかもしれないと私は読んだが、私はどのように表示されません。カーソルを前面に表示してからすべてを選択して反復する必要があります。

+0

ネストされたセットはあなたの唯一の選択肢ではありません。クロージャーテーブルも検討する価値があります。 – eggyal

+0

実際に、私は今午後閉鎖テーブルを発見しました!彼らは有望に見えますが、移動操作を非常にうまく処理しません。 http://www.mysqlperformanceblog.com/2011/02/14/moving-subtrees-in-closure-table/その意味で、彼らはネストされたセットのようなものです。私は勉強を続けます。 – Metaphile

+0

あなたのニーズに合ったデータ構造を選択することは、さまざまな操作を行う必要がある頻度を理解することです。グラフがかなり静的で、パスを調べなければならない場合は、おそらく隣接リストが最適な選択肢ではないでしょう。ただし、グラフが非常に動的であり、与えられたノードのすぐ隣にある隣接ノードより多くを検査する必要がほとんどない場合は、理想的なソリューションになる可能性があります。 – eggyal

答えて

0

これは最大でread : writeです。あなたが非常に高い読書率を持っているなら、完全な関係のテーブルを作るのは非常に役に立ちます。一時的ではありません。

擬似的アプローチ(未実際のコード!):関係を更新中

1. node(1) has child node(2) 
    -> Insert a row with (parent_id = 1, child_id = 2, direct = True) 

2. node(2) has child node(3) 
    -> Insert a row with (parent_id = 2, child_id = 3, direct = True) 
    -> Choose all ascendants of node(2) 
    -> Ascendants of node(2) : [node(1)] 
    -> Insert a row with (parent_id = 1, child_id = 3, direct = False) 

3. To retrieve all descendants of node(1) 
    -> SELECT child_id FROM [table] WHERE parent_id = 1; 

4. To retrieve children of node(1) 
    -> SELECT child_id FROM [table] WHERE parent_id = 1 AND direct = True; 

5. To retrieve all ascendants of node(3) 
    -> SELECT parent_id FROM [table] WHERE child_id = 3; 

6. To retrieve parent of node(3) 
    -> SELECT parent_id FROM [table] WHERE child_id = 3 AND direct = True; 

+-----------+----------+--------+ 
| parent_id | child_id | direct | 
+-----------+----------+--------| 
|   1 |  2 | True | 
|   1 |  3 | False | 
|   2 |  3 | True | 
.... 
+-----------+----------+--------+ 
Index 1 on (parent_id, direct) 
Index 2 on (child_id, direct) 

このapprocheは悪い性能を有しています。自己責任。

関連する問題