2008-08-21 3 views
1

私はエッジとしてMySQLデータベースにエンコードされたツリーを持っています:どのようにMySQLデータベースの再帰的不変量を維持するには?

CREATE TABLE items (
    num INT, 
    tot INT, 
    PRIMARY KEY (num) 
    ); 
CREATE TABLE tree (
    orig INT, 
    term INT 
    FOREIGN KEY (orig,term) REFERENCES items (num,num) 
    ) 

ツリー内の各リーフに対して、items.totは誰かによって設定されます。内部ノードの場合、items.totはその子ノードの合計である必要があります。次のクエリを繰り返し実行すると、目的の結果が生成されます。

UPDATE items SET tot = (
    SELECT SUM(b.tot) FROM 
     tree JOIN items AS b 
     ON tree.term = b.num 
     WHERE tree.orig=items.num) 
    WHERE EXISTS 
     (SELECT * FROM tree WHERE orig=items.num) 

(実際には動作しませんが、それはポイントの横です)

データベースが存在し、不変量がすでに満たされているとします。

問題は次のとおりです。

この要件を維持しながらDBを更新する最も実際的な方法は何ですか?更新は、ノードを移動させるか、リーフノード上のtotの値を変更することがあります。リーフノードはリーフノードのままであり、内部ノードは内部ノードとして残り、すべてが適切なツリーとして残ると仮定できます。

私はいくつかの考えを持っていました:

  • すべての更新の後、完全失効はすべてを再計算します(Um ...いいえ)
  • 任意の行が更新されます
    • これは再帰的です(トリガの更新、トリガの更新などを更新します)。
    • 動作しません.MySQLはトリガを起動したテーブルを更新できません
  • 更新される行の親の更新をスケジュールするトリガーを設定する
    • これは反復的です(スケジュールから項目を取得し、それ以上の項目をスケジュールする)
    • それを正しくするためにクライアントコードを信頼していますか?
    • 利点は、更新プログラムが正しく注文された場合、合計がコンピュータである必要があることです。しかし、その順序はそれ自身の複雑さです。

理想的な解は、他の「凝集不変量」に一般化されます。

FWIWこれは「少し外れている」ことを知っていますが、私はこれを楽しんでいます。それをすることで不可能です:-)

答えて

1

問題は、SQLでの再帰が明確です。あなたは、葉の親の親を取得する必要があります...それは合計を更新します(古いものを減算し、新しいものを追加するか、または再計算します)。ツリーの構造を見るためには何らかの形式の識別子が必要であり、すべてのノードの子ノードと更新するリーフの親/パスのリストを取得する必要があります。

この方法では、一定のスペース(テーブルに2つのカラムが追加されますが、テーブルは1つだけ必要です。後でジョインすることもできます)。私は前回のトラバーサルとポストオーダートラバーサルでそれぞれ計算された '左'と '右'の列(明らかにそれらの名前ではない)を使用して階層形式を使用した構造体を使っていました。これらは毎回再計算する必要はありません。

答えとしてこの方法が嫌な場合に備えて、このディスカッションを続行する代わりに、using this method in mysqlページを見てみましょう。しかし、あなたがそれを好きなら、投稿/編集して、私はしばらく時間をとり、明確にするでしょう。

+0

興味深いアプローチです。私が気に入らないのは、 'N * Log(N)'のようなものを使用していることです。また、私は主要な改造を必要とするいくつかのバージョン管理の制約があります。 - 残念ながら、著者は集計値を更新する方法に決して慣れていません。私はいくつかのアプローチについて考えることができますが、その実装に依存します。私はこれ以上考えなければならないでしょう。 ([非常に古い]回答から移動しました) – BCS

+0

形式を記述するmysqlドキュメントへのリンクを更新しました。 – nlucaroni

1

私はあなたの質問を正しく理解していますが、これはうまくいくかもしれません。My take on trees in SQL

リンクされたポストはデータベースにツリーを格納する方法を説明しています - その場合はPostgreSQLですが、その方法ははっきりしているので、どのデータベースでも簡単に採用できます。あなたが簡単にすべてのノードがNは、ルートノードからKの距離で約N簡単のSELECTクエリで修飾されたノードKに依存して更新することができ、この方法では

私はあなたの木が本当に深くないことを願っています:)。

Good Luck!

関連する問題