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
リーフ ノードの値が変更されたりする場合があります。葉ノードは葉ノードのままであり、内部ノードは内部ノードのままであり、全体は適切なツリーのままであると想定できます。
私が持っていたいくつかの考え:
- 完全な無効化、更新後、すべてを再計算します (ええと...いいえ)
- アイテム テーブルにトリガーを設定して、更新された行の親を更新します。
- これは再帰的です(更新は更新をトリガーし、更新をトリガーします...)
- 動作しません。MySQL はトリガーを開始したテーブルを更新できません
- 更新される任意の行の親の更新をスケジュールするようにトリガーを設定します
- これは反復的です(スケジュールからアイテムを取得し、それを処理してさらにアイテムをスケジュールします)
- 何がこれを開始しますか?クライアントコードを信頼して正しく取得しますか?
- 利点は、更新が正しく順序付けられている場合、計算する必要がある合計が少なくなることです。しかし、その順序はそれ自体が複雑です。
理想的な解決策は、他の「集約不変条件」に一般化されます
FWIW私はこれが「少しやり過ぎ」であることを知っていますが、私は楽しみのためにこれをやっています(楽しい:動詞、それを行うことによって不可能を見つける. :-)