3

ここで、親子関係を維持するためにこの手法をよく使用するという質問があります。つまり、すべてのエンティティをparent_id列を持つ1つのテーブルに保存し、最上位のすべての親はparent_id列に0を持っています。これは良い正規化された手法です。同意しますが、欠点もあり、遅くて非効率的です。これは主に、ツリーを作成するためにクエリを何度も実行する必要がある各親のような再帰が原因です。

SELECT id FROM `table` WHERE parent_id=something

query を何度も実行してサーバーに負荷をかけることで、任意のプログラミング言語でそれを実行しようとする可能性のあるソリューションを見てきました。ストアドプロシージャを提供しているものもありますが、再帰も含まれています。

私の質問は、ツリーの 1 つのデータベース クエリ (結合またはサブクエリ) でそれを実行できるかということです。

  • 深さを知っている場合、または深さを知らない場合は?

  • 可能であれば、どのようにしてどの子の最上位の親 (つまり、parent_id=0) を取得できますか?

  • それが不可能な場合、なぜこの手法がそれほど有名なのですか?それには欠陥がありますか、それとも別の解決策がありますか?

    SQLフィドルを追加しましたが、スキーマしかありません

フィドル

4

2 に答える 2

1

レベル数やデータ数が多い場合、これは実用的ではありません。

それ以外の場合は、再帰関数の動作をエミュレートすることができます。同じパフォーマンスが得られなくても、データが少なくても、レベルが多すぎても問題ありません。

一般的な手順は次のとおりです。

  1. 特定の親について、その ID を持つレコードを選択します
  2. また、それを PARENT_ID としてレコードを選択し、これを前のレコードと UNION します。
  3. ステップ 2 のサブクエリは第 1 レベルの子を提供するため、ID を選択するクエリを記述し、これを「where PARENT_ID IN (sub-select)」という 3 番目のクエリでサブ選択として使用できます。
  4. これはステップ 3 に類似しており、この方法で進みます。

これは次のようになります: ( Fiddle here を参照してください)

select *
from prarent P0
where id = 3

union 

select *
from prarent P1
where parent_id = 3

union 

select *
from prarent P2
where parent_id in
 (  select distinct id
    from prarent P1
    where p1.parent_id = 3
 )

union 

select *
from prarent P3
where parent_id in
 (  select distinct id
    from prarent P2
    where parent_id in
    (  select distinct id
       from prarent P1
       where p1.parent_id = 3
    )
 )
于 2013-07-16T18:59:37.007 に答える