葛のメモ帳

自分で調べたことを忘れないためにメモっておきます

葛のメモ帳

自分で調べたことを忘れないためにメモっておきます


【SQL】アンチパターン2章:ナイーブツリー(素朴な木)

おことわり

自分がわかるように解説記事を書いていきます。間違いがあれば指摘ください

目的:階層構造を格納して、クエリを実行したい

  • あなたは、ニュースサイトの記事に対してコメント機能を実装します。
  • コメントはスレッド形式
  • ディスカッションも可能で、トピック毎に枝分かれする

あなたは思いつきました。

コメントに親コメントを持たせれば再起的にrootコメントまで辿れるやろ

アンチパターン: 常に親のみに依存する

  • データ構造の学習などを経験していれば誰しもがこの方法をまず最初に思いつくと思います。
    • root, branch, leaf, node...
  • 再帰関数を用意してプログラムでは実装できてもSQLではどうでしょうか?
n世代子のコメントを取得...?

いつまでそれ書きますか?

SELECT
FROM Comments c1
    LEFT OUTER JOIN Comments2
        ON c2.parrent_id = c1.comment_id -- 2階層
    LEFT OUTER JOIN Comments3
        ON c3.parrent_id = c2.comment_id -- 3階層
・・・
コメント追加、移動
  • これは容易にできますね。
  • 親のIDに紐づけて登録・更新するだけです
削除
  • ツリー整合性を保つために、ツリー全体の検索して親のすげ替えをしていく必要がありそうですね・・
  • メンテしずらい

解決策:代替ツリーモデル

経路列挙(シンプルだがジェイウォーク)

  • そのノードまでのパスを /2/4/5/5のように保存する方法
  • ジェイウォークになりそうですね

入れ子集合(やや難解)

  • 子孫の集合に関する情報を各ノードに格納する
  • nsleft, nsright
  • これはそこそこ複雑なので今回は割愛します

閉包テーブル(シンプル&フレキシブル)

  • 直接の親子関係だけでなく、ツリー全体のパスを格納する
  • ある意味これも交差テーブルの応用

ツッコミどころの解消

要素の検索
  • コメント4の親の検索は、子孫が4を調べれば良い
  • コメント4の子の検索は、先祖が4を調べれば良い
更新
  • 同じ
追加
  • 親要素を元に追加するだけで良い
削除
  • CommentテーブルとTreePathテーブルの両方を削除しないといけない
  • CASCADEをつければCommentさえ削除しとけば大丈夫

最後に

  • これは自分も知らなかったので勉強になった