私は答えはノーだと思っていますが、誰もがSQL(MySQL)の任意の深さまでツリー構造をクロールする方法についての洞察を持っていたが、単一のクエリでそれが大好きです
より具体的には、ツリー構造のテーブル(id、data、data、parent_id)、およびテーブル内の1つの行を指定すると、all子孫(child/grandchild/etc)、またはそのために取得できますすべての祖先(親/祖父母/など)は、単一のクエリを使用して、それがどれだけ上下するかを知らずに重要ですか?
または、新しい結果がなくなるまでより深くクエリを続ける、何らかの再帰要求を使用していますか?
具体的には、RubyとRailsを使用していますが、それはあまり意味がないと思います。
はい、これは可能です。これは、ここで最もよく説明されているように、変更された事前順序ツリートラバーサルと呼ばれます。
Joe CelkoのSQL for Smartiesのツリーと階層
実用的な例(PHP)がここに提供されています
http://www.sitepoint.com/article/hierarchical-data-database/2/
以下にいくつかのリソースを示します。
基本的に、ストアドプロシージャまたはクエリで何らかのカーソルを実行するか、隣接テーブルを作成する必要があります。 dbの外での再帰は避けたいと思います。ツリーの深さによっては、本当に遅く/スケッチする可能性があります。
ダニエル・ビアズリーの答えは、あなたが尋ねている主な質問が「私の子供たちは何ですか」と「私の両親は何ですか」である場合、まったく悪い解決策ではありません。
Alex Weinsteinに対応して、この方法は実際には、Celko手法よりも親の動きのノードの更新が少なくなります。 Celkoの手法では、左端のレベル2ノードが右端のレベル1ノードの下に移動した場合、ノードの子だけでなく、ツリー内のほとんどすべてのノードを更新する必要があります。
ただし、ダニエルはルートへのパスを間違った方法で保存している可能性があります。
クエリが次のようになるように保存します
SELECT FROM table WHERE ancestors LIKE "1,2,6%"
これは、mysqlが「先祖」列のインデックスを使用できることを意味します。これは、先頭の%では実行できません。
前にこの問題に出くわし、1つの奇抜なアイデアがありました。 直接の祖先のIDを連結した文字列である各レコードのフィールドをルートに戻すことができます。
このようなレコードがあると想像してください(インデントは階層を意味し、数字はid、祖先です)。
次にid:6の子孫を選択に、これを行うだけです
SELECT FROM table WHERE ancestors LIKE "%6,2,1"
先祖の列を最新の状態に保つことは、あなたにとって価値があることよりも厄介かもしれませんが、どのDBでも実行可能なソリューションです。
Celkoの手法(ネストセット)はかなり優れています。また、「祖先」フィールドと「子孫」フィールドと「距離」フィールドを持つ隣接テーブルを使用しました(たとえば、直接の子/親の距離は1、孫/祖父母の距離は2など)。
これは維持する必要がありますが、挿入の場合はかなり簡単です:トランザクションを使用してから、直接リンク(親、子、距離= 1)をテーブルに配置し、距離を追加して既存の親と子の選択を無視します(機会があればSQLをプルアップできます)、パフォーマンスのために3つのフィールドのそれぞれにインデックスが必要です。このアプローチがいのは、削除の場合です...基本的に、影響を受けたすべてのアイテムをマークしてから、それらを再構築する必要があります。しかし、これの利点は、任意の非循環グラフを処理できることです。一方、ネストされたセットモデルはストレート階層しか実行できません(たとえば、ルート以外の各アイテムには1つの親しかありません)。
これは間違いなく実行でき、SQLにとってそれほど複雑ではありません。この質問に答え、mysql手続きコードを使用した実際の例をここに提供しました。
ブース:満足したら、回答の1つを承認済みとしてマークする必要があります。
SQLはチューリング完全言語ではありません。つまり、この種のループを実行することはできません。 SQLとツリー構造を使用して非常に巧妙なことを実行できますが、任意の深さの階層に対して「階層内に」特定のIDを持つ行を記述する方法は考えられません。
あなたの最善の策は、@ Danが示唆したものに沿ったものです。これは、他のより有能な言語でツリーをただ操作することです。実際には、ループを使用して汎用言語でクエリ文字列を生成できます。クエリは、探している階層の深さを反映する複雑な一連の結合(またはサブクエリ)です。ループや複数のクエリよりも効率的です。
https://stackoverflow.com/questions/27013093/recursive-query-emulation-in-mysql で説明されている「With Emulator」ルーチンを使用しました( https:// stackoverflow .com/users/1726419/yossico )。これまでのところ、非常に良い結果が得られています(パフォーマンスに関して)が、豊富なデータや検索対象の多数の子孫はありません。