この結果を再帰的に取得するのは難しいです(可能ですが)。ただし、通常はあまり効率的ではなく、多くの この問題を解決するためのより良い方法。
基本的に、ツリーを一番上までトレースする追加の列でテーブルを拡張します。これを「アップチェーン」と呼びます。これは、次のような長い文字列です。
name | id | parent_id | upchain
root1 | 1 | NULL | 1:
root2 | 2 | NULL | 2:
root1sub1 | 3 | 1 | 1:3:
root1sub2 | 4 | 1 | 1:4:
root2sub1 | 5 | 2 | 2:5:
root2sub2 | 6 | 2 | 2:6:
root1sub1sub1 | 7 | 3 | 1:3:7:
テーブルのトリガーを使用して、このフィールドを最新の状態に保つのは非常に簡単です。 (用語についてはお詫びしますが、私は常にSQL Serverでこれを行ってきました)。レコードを追加または削除したり、parent_idフィールドを更新したりするたびに、ツリーのその部分のアップチェーンフィールドを更新する必要があります。親レコードのアップチェーンを取得し、現在のレコードのIDを追加するだけなので、これは簡単な作業です。すべての子レコードは、LIKEを使用して簡単に識別され、アップチェーンに開始文字列が含まれるレコードを確認します。
あなたが効果的に行っているのは、少し余分な書き込みアクティビティを大きなと交換することです。 データを読みに来たときに保存します。
ツリー内の完全なブランチを選択する場合、それは簡単です。ノード1の下にブランチが必要だとします。ノード1にはアップチェーン「1:」があるため、そのノードの下にあるツリーのブランチ内のノードには、「1:...」で始まるアップチェーンが必要であることがわかります。だからあなたはこれをするだけです:
SELECT *
FROM table
WHERE upchain LIKE '1:%'
これは非常に 高速(もちろん、アップチェーンフィールドにインデックスを付けます)。ボーナスとして、部分的なツリーの検索、ツリー内のレベルなど、多くのアクティビティが非常に簡単になります。
これは、大規模な従業員のレポート階層を追跡するアプリケーションで使用しましたが、ほとんどすべてのツリー構造(パーツの内訳など)に使用できます。
注(興味のある方へ):
- SQLコードのステップバイステップは示していませんが、原則を理解すれば、実装は非常に簡単です。私は優れたプログラマーではないので、経験から話しています。
- テーブルにすでにデータがある場合は、アップチェーンを最初に同期させるために1回の更新を行う必要があります。繰り返しますが、コードはトリガーのUPDATEコードと非常に似ているため、これは難しくありません。
- この手法は、他の方法では見つけるのが難しい循環参照を識別するための優れた方法でもあります。