2009-06-29 7 views
5

私の心の中で、これにスーパー単純な再帰的解決策がなければならないと感じています。祖先のリストからツリーを構築するもっとも簡単な方法

私はクローズテーブルとしてSQLに格納されたツリーを持っています。ツリーは(1(2(3)、4))のようになり、言語はMySQLのSQLとPHP 5.3です。

閉鎖テーブルはこのようです:

+----------+------------+ 
| ancestor | descendant | 
+----------+------------+ 
|  1 |   1 | 
|  2 |   2 | 
|  3 |   3 | 
|  4 |   4 | 
|  1 |   2 | 
|  1 |   3 | 
|  1 |   4 | 
|  2 |   3 | 
+----------+------------+ 

私は非常に簡単に先祖を照会することができます:どのように私は簡単にこのデータをPHPでツリーを構築することができ

SELECT descendant AS id, GROUP_CONCAT(ancestor) as ancestors FROM 
closure GROUP BY (descendant); 

+----+-----------+ 
| id | ancestors | 
+----+-----------+ 
| 1 | 1   | 
| 2 | 2,1  | 
| 3 | 3,1,2  | 
| 4 | 4,1  | 
+----+-----------+ 

?よりスマートなクエリを使用して、より多くのデータをMySQLから取得できますか?

答えて

4

最初のキーは、SQL結果を祖先の数でソートすることです。私はPHPでこれを行いました。なぜなら、複数桁の数字の複雑さを避けるからです。

これは、有効に挿入できる順序でノードのリストを提供します。

Array 
(
    [1] => Array 
     (
      [0] => 1 
     ) 

    [4] => Array 
     (
      [0] => 4 
      [1] => 1 
     ) 

    [2] => Array 
     (
      [0] => 2 
      [1] => 1 
     ) 

    [3] => Array 
     (
      [0] => 3 
      [1] => 1 
      [2] => 2 
     ) 

) 

この時点で、私は、キー、先祖のリストのみを気にしないでください。ツリーを通る経路は、利用可能なノードと残りの祖先との交差点の間に見つけることができる。

+1

興味深い!それは理にかなっています、両親は常に彼らの子供よりも少ない祖先を持つでしょう。 –

2

私はクロージャーテーブルを使用しました(私には奇妙に聞こえます...私はそれが何か他のものと聞いたことを忘れていました)が、祖先と子孫の間に "距離"直接子孫(子)と間接子孫(孫など)を区別します。

技術的には、リストされたテーブルは、データを有向非循環グラフで記録することができるため、セクションを除いた階層ツリーを構築することはできません。

編集:

私はPHPに照会していた場合、私はおそらくちょうどGROUP_CONCATを使用してO/Wテーブル自体に選択したい - あなたはとにかく手続き物事を処理することになるだろう、なぜいません最も簡単な形式のクロージャーテーブルの適切なサブセットを取得するだけですか?

また、クロージャテーブルには注文情報が格納されないことに注意してください(重要な場合)。

この階層データのツリーの側面が非常に重要で、データの格納方法を選択する場合は、順序を維持し、ツリーを再構築するのがはるかに簡単なnested set modelを検討してください。

+1

ネストされたセットには参照整合性がなく、他の多くの操作にはコストがかかり/困難です。 (すなわち:削除) –

関連する問題