2009-05-12 19 views
5

ツリーを表すテーブルを作成する最適な方法は何ですか? 大きなデータでうまく動作する選択、挿入、更新、削除を実装したいと思います。 たとえば、selectは "Expand All"をサポートする必要があります - 指定されたノードのすべての子(および子)を取得します。SQL Server 2005で高性能ツリービューを実装する方法

答えて

8

CTEさんの使用。ツリー状のテーブル構造を考えると

WITH v (id, parent, level) AS 
     (
     SELECT id, parent, 1 
     FROM table 
     WHERE parent = 0 
     UNION ALL 
     SELECT id, parent, v.level + 1 
     FROM v 
     JOIN table t 
     ON  t.parent = v.id 
     ) 
SELECT * 
FROM v 

id parent name 
1 0  Electronics 
2 1  TV 
4 2   LCD 
5 2   Plasma 
3 1  Hi-Fi 
6 3   Amplifiers 
7 3   Speakers 

のみ取得するparent = @parentparent = 0を交換してください:

id parent name 
1 0  Electronics 
2 1  TV 
3 1  Hi-Fi 
4 2  LCD 
5 2  Plasma 
6 3  Amplifiers 
7 3  Speakers 

、このクエリはidparentと深さのレベルを返しますが、ツリーとして注文しました木の枝。

table (parent)にインデックスがある場合、このクエリは非常に大きなテーブルで効率的に動作します。これは再帰的にINDEX LOOKUPを使用して各ペアレントのすべてのチャイルドンを検索するためです。 @parentは、ブランチのルートである

WITH v (id, parent, level) AS 
     (
     SELECT id, parent, 1 
     FROM table 
     WHERE parent = 0 
     UNION ALL 
     SELECT id, parent, v.level + 1 
     FROM v 
     JOIN table t 
     ON  t.parent = v.id 
     ) 
UPDATE table t 
SET  column = newvalue 
WHERE t.id IN 
     (
     SELECT id 
     FROM v 
     ) 

は、特定のブランチ、問題を更新します。

+0

テーブルの構造について詳しく教えていただけますか? このクエリは大きなデータベースでうまく動作しますか? – SirMoreno

+0

ありがとうございます。 詳細な更新方法を教えてください。 - 親の下のすべてのノードを更新しますか? (孫を含む) – SirMoreno

+0

ねえ、私はこれを動作させようとしています、そして、それはvqの項目dosentの仕事のように見えます、私は2008年に努力しています。また、テーブルに表示されていないので、データベースにレベルを保存する必要がありますか? –

2

Joe Celko's book on trees and hierarchiesで、階層の問題に取り組むためのさまざまな方法があります。あなたが選ぶモデルは、あなたの体重の見通しと更新の比較と複雑さの違いによって決まります。隣接リストモデルを使用してルックアップを非常に高速に(特にノード内のすべての子を取得するために)行うことができますが、ツリーの更新は遅くなります。

+0

ありがとう、私はそれを探します。 ユニオンはすべて再帰的に効率的ですか? mssql 2005にはツリーを扱う新しい方法があると聞いていますが、大きなDBでうまく動作するかどうかは分かりますか? – SirMoreno

+0

CTE内のUNION ALLは再帰的ですが、SQL Serverがその背後でそれをどのように処理するか、またはパフォーマンスの調整があるかどうかはわかりません。パフォーマンスについて確かめるために、CTEで十分な大規模テストを行っていません。 –

3

あなたは自分自身にこれらの質問を最初にお願いします: 1)修正対修正の比は何ですか? (=ほとんど静的なツリーか、絶えず変化していますか?) 2)ツリーがどのくらい深く、どれくらい大きくなると思いますか?

ネストされたセットは、ブランチ全体で操作が必要なほとんど静的なツリーに最適です。それは問題のない深い木を扱う。

マテリアライズドパスは、拘束/予測可能な深度を持つ動的(変更)ツリーに適しています。

再帰的なCTEは、非常に小さいツリーには理想的ですが、ブランチ操作(「このブランチのすべての子を取得...」)は深い/大きなツリーで非常に高価になります。

http://www.sqlteam.com/article/more-trees-hierarchies-in-sql

+1

私のツリーは非常に動的で、多くのアップデートがありますが、多くのものも選択されています。 そして私は10-15レベルとして深くなることができるようにしたいと思います。 この記事はネストされたセットについて見つかりました: http://sqlblog.com/blogs/adam_machanic/archive/2006/07/12/swinging-from-tree-to-tree-using-ctes-part-1-adjacency -to-nested-sets.aspx この資料に記載されているネストされたセットは、私の最善の選択肢ですか?ありがとうございます。 ありがとうございます。 – SirMoreno

1

は、最良のオプションは、ここで簡単に説明されているパス列挙モデルを、のようです。非常に効率的な読み込みと非常に簡単に書くことができます。

0

私は驚いて誰も言及していないClosure Tableと一緒に行く:あなたは、多くの更新と選択している場合は

関連する問題