web-dev-qa-db-ja.com

リレーショナルDBにツリー構造を保存する既知の方法は何ですか?

「FKを親に置く」メソッド があります。つまり、各レコードはその親を指します。
読み取りアクションは難しいが、保守は非常に簡単です。

そして、「ディレクトリ構造キー」メソッドがあります:

0001.0000.0000.0000 main branch 1
0001.0001.0000.0000 child of main branch one
etc

これは非常に読みやすいですが、保守が困難です。
他の方法とその短所/長所は何ですか?

39

いつものように、最善の解決策はありません。各ソリューションにより、さまざまなことが簡単または難しくなります。最適なソリューションは、どの操作を最も多く行うかによって異なります。

parent-idを使用した単純なアプローチ:

長所:

  • 実装が簡単

  • 大きなサブツリーを別の親に簡単に移動できます

  • 挿入は安い

  • SQLで直接アクセスできる必要なフィールド

短所:

  • ツリー全体を取得するのは再帰的であるため、費用がかかります

  • すべての親を見つけることも高価です(SQLは再帰を知りません...)

変更された先行予約ツリー走査(開始点と終了点の保存):

長所:

  • ツリー全体を取得するのは簡単で安価です

  • すべての親を見つけるのは安い

  • SQLで直接アクセスできる必要なフィールド

  • ボーナス:親ノード内の子ノードの順序も保存します

短所:

  • 多くのノードを更新する必要があるため、挿入/更新は非常に高価になる可能性があります

各ノードでのパスの保存:

長所:

  • すべての親を見つけるのは安い

  • ツリー全体を取得するのは簡単です

  • 挿入は安い

短所:

  • ツリー全体を移動するのは高価です

  • パスを保存する方法によっては、SQLで直接操作することはできないため、変更する場合は常にフェッチして解析する必要があります。

データが変更される頻度に応じて、最後の2つのいずれかを選択します。

参照: http://media.pragprog.com/titles/bksqla/trees.pdf

49
Baju

変更された先行予約ツリートラバーサル

これは、非再帰関数(通常は1行のSQL)を使用してデータベースからツリーを取得する方法ですが、更新するのが少し難しくなります。

Diagram showing numbered hierarchical tree **

Sitepointの記事のセクション2 データベースへの階層データの保存 詳細.

18
TRiG

階層データ構造を保存する「黄金の方法」は、階層データベースを使用することです。たとえば、HDBなど。これは、ツリーを非常にうまく処理するリレーショナルデータベースです。より強力なものが必要な場合は、LDAPが役立ちます。

SQLデータベースは、この抽象的なトポロジには適していません。

4
Borealid

リレーショナルデータベースを使用してツリー構造を構築するのは難しいとは思いません。

ただし、この目的にはオブジェクト指向データベースの方がはるかに優れています。

オブジェクト指向データベースの使用:

parent has a set of child1  
child1 has a set of child2  
child2 has a set of child3  
...  
...

オブジェクト指向データベースでは、この構造を非常に簡単に構築できます。

リレーショナルデータベースでは、親に対する外部キーを維持する必要があります。

parent  
id  
name  

child1  
parent_fk  
id  
name 

child2  
parent_fk  
id  
name  

..

基本的に、ツリー構造を構築している間に、これらのすべてのテーブルを結合する必要があります。または、テーブルを反復処理できます。

foreach(parent in parents){
   foreach(child1 in parent.child1s)
    foreach(child2 in child1.child2s)

...
0
DarthVader