しばらくの間、私は SQL で階層を処理する最善の方法と格闘してきました。隣接リストの制限と MPTT/ネストされたセットの複雑さに不満を感じた私は、単純なnode_key/node_key/...
文字列として代わりにキー パスを単純に保存することを考え始めました。3 つの手法の長所と短所をまとめることにしました。
ノードの作成/削除/移動に必要な呼び出しの数:
- 隣接性 = 1
- MPTT = 3
- パス = 1 (そのパスを含むすべてのノードで、古いノード パスを新しいノード パスに置き換えます)
ツリーを取得するために必要な呼び出しの数:
- 隣接性 = [サブレベルの数]
- MPTT = 1
- パス = 1
ノード/祖先へのパスを取得するために必要な呼び出しの数:
- 隣接性 = [スーパーレベルの数]
- MPTT = 1
- パス = 0
サブノードの数を取得するために必要な呼び出しの数:
- 隣接性 = [サブレベルの数]
- MPTT = 0 (左右の値から算出可能)
- パス = 1
ノードの深さを取得するために必要な呼び出しの数:
- 隣接性 = [スーパーレベルの数]
- MPTT = 1
- パス = 0
必須の DB フィールド:
- 隣接性 = 1 (親)
- MPTT = 3 (親、右、左)
- パス = 1 (パス)
結論
ストアド パス手法は、1 つを除くすべてのユース ケースで、他の手法と同じか、または少ない呼び出しを使用します。この分析によると、パスの保存は明らかに勝者です。言うまでもなく、実装がはるかに簡単で、人間が読めるなどです.
問題は、保存されたパスは MPTT よりも強力な手法と見なされるべきではないということです。保存されたパスがより一般的に使用される手法ではないのはなぜですか? また、特定のインスタンスで MPTT を介して保存されたパスを使用しないのはなぜですか?
また、この分析が不完全だと思われる場合は、お知らせください。
アップデート:
保存されたパス ソリューションではできなくても、MPTT ですぐに実行できることが少なくとも 2 つあります。
- 追加のクエリなしで、各ノードのサブノード数を計算できます (上記)。
- 特定のレベルでノードに順序を課します。他のソリューションは順不同です。