SQL クロージャ テーブルに頭を悩ませているので、見つけたいくつかの例を理解するための助けが必要です。
sample_items
次の階層データで呼び出されるテーブルがあるとします。
id name parent_id
1 'Root level item #1' 0
2 'Child of ID 1' 1
3 'Child of ID 2' 2
4 'Root level item #2' 0
ツリー構造は事実上次のようになります。
id
| - 1
| | - 2
| | - 3
| - 4
ツリーのクエリ (特定の ID のすべての子孫を検索するなど) を容易にするために、この優れた SO 投稿 で Bill Karwin によって説明されている方法sample_items_closure
を使用して呼び出されるテーブルがあります。また、必要に応じて直接の子または親を照会するためのオプションの列も使用します。この方法を正しく理解していれば、クロージャー テーブルのデータは次のようになります。path_length
ancestor_id descendant_id path_length
1 1 0
2 2 0
1 2 1
3 3 0
2 3 1
1 3 2
4 4 0
のすべての行には、それ自体とそのすべての先祖の両方sample_items
のエントリがテーブルに含まれています。sample_items_closure
これまでのところ、すべてが理にかなっています。
ただし、他のクロージャー テーブルの例を調べているときに、ルート レベル (ancestor_id 0) にリンクし、パスの長さが 0 である行ごとに追加の祖先を追加するものに出くわしました。上記と同じデータを使用すると、次のようになります。クロージャーテーブルは次のようになります。
ancestor_id descendant_id path_length
1 1 0
0 1 0
2 2 0
1 2 1
0 2 0
3 3 0
2 3 1
1 3 2
0 3 0
4 4 0
0 4 0
より良いコンテキストを提供するために、そのサイトで使用されている選択クエリを、私の例に合うように変更したものを次に示します。
SELECT `id`,`parent_id` FROM `sample_items` `items`
JOIN `sample_items_closure` `closure`
ON `items`.`id` = `closure`.`descendant_id`
WHERE `closure`.`ancestor_id` = 2
この方法に関連する 2 つの質問があります。
質問1:
各子孫をルート レベル (id 0) にリンクする追加の行が追加されるのはなぜですか?
質問2:
前の祖先の path_length + 1 ではなく、これらのエントリの path_length が 0 になるのはなぜですか? 例えば:
ancestor_id descendant_id path_length
1 1 0
0 1 1
2 2 0
1 2 1
0 2 2
3 3 0
2 3 1
1 3 2
0 3 3
4 4 0
0 4 1
おまけの質問:ツリーの完全な構造が既にクロージャ テーブルで表現されているのに、一部の例にまだ隣接リスト (私の例では のparent_id
列) が含まれているのはなぜですか?sample_items