これらの制約を考えると、方法はありません。このような場合は、すべてを取得します。 ツリーを作成して「ヒル」クライアント側を構築するか、特定のケースで最もパフォーマンスが高いものなら何でも再帰クエリを実行します。
固定数の階層レベルを持つという追加の制約があります 、複数のJOINを使用してこれを行うことができます。
一般的なケースでは、これらの制約を克服できるようにするために、いくつかの構造変更があります。実際には、「これは私のテーブル構造です」という制約を緩和して、フィールドを追加できるようにします。
たとえば、ノード構造をleft_id
で補足できます。 値を指定し、ツリーの深さ優先にアクセスするときに、すべてのノードIDが順番に並んでいることを確認します。
1 --- 2 -+- 3 -+- 4
| |
| +- 5
+- 6 --- 7
この場合、ノード3は値「5」を格納し、ノード6は値「7」を格納し、ノード2も値「7」を格納します。 各ノードは、子のLeftIDと自身のIDの間の最大値をLeftIDに格納します 。
したがって、子のないノードのLeftIDはIDと同じです。ノード1はLeftID7を持ちます。これはLeftIDが2であり、6から取得したためです。
この状況では、カウント シーケンスに穴がない場合、ノードは簡単です。ノードのすべての子孫は、IDが開始ノードのIDとそのLeftIDの間にあるノードです。葉は、LeftIDがIDと等しいことで識別されます。
したがって、「ノードID17から派生するすべてのリーフ」は
になります。SELECTchild。*FROMtable AS parentJOIN table AS childON(child.id> parent.id AND child.id <=parent.leftid)/*子孫/ WHERE child.id =child.leftid / リーフ/AND parent.id =17; / 親は17歳です
この構造は、整理と分岐を実行できるようにする場合に維持するのが面倒です。これは、整理のポイントから分岐のポイントまでのすべてのノードと、移動されたノードの番号を変更する必要があるためです。
カウントのみに関心がある場合のもう1つの可能性は、子カウンターを保持することです。これは、繰り返し更新し、すべての葉を選択し、それらのカウンターを0に設定することで維持できます(LEFT JOINを介して葉を識別します)。次に、NULLカウンターを持つすべての親で、NULL以外のカウンターを持つ子があり、カウンターをSUM()
に更新します。 子供のカウンターとCOUNT()
の数 子供自身の;すべてのノードにNULL以外のカウンターがあるため、更新された行の数がゼロになるまで続行します。整理して分岐した後、すべてのカウンターをNULLに設定して繰り返します。
この最後のアプローチでは、階層レベルごとにリフレクティブ結合が必要です。