2012-02-05 1 views
2

この特定の問題が以前に尋ねられたことがない(似たような質問は見つかりませんでした)ことを願っています。もしそうなら、私をそのページに静かにリンクしてください。1つのクエリでDBツリー構造を並べ替えることができますか?

DB(MySQL - InnoDB)のツリー構造で作業しています。ノードとnode_indexという2つのテーブルがあります。最初のテーブル(ノード)は実際のデータを保持し、node_indexは階層構造を追跡します。 node_indexテーブル(重要な部分)は、次のようになります。

+-------------+-------------+--------+----------+ 
| node_id  | path  | depth | order | 
+-------------+-------------+--------+----------+ 
| 0   | 0   | 1  | 1  | 
| 1   | 0.1   | 2  | 1  | 
| 2   | 0.2   | 2  | 2  | 
| 3   | 0.2.3  | 3  | 1  | 
| 4   | 0.2.4  | 3  | 2  | 
| 5   | 0.5   | 2  | 3  | 
+-------------+-------------+--------+----------+ 

Node_idは、ノードテーブル内のidの外部キーです。この質問の文脈のためにノードテーブルの構造が何であるかは重要ではない。

完全なツリーを生成している間に、node_indexから順番にすべてを選択することができ、正しい構造を1つのクエリで得ることができます。問題は、これは注文設定を尊重しないことです。なぜなら、すべての親+レベルの組み合わせに対して、これはIDでノードを並べ替えるためです。変更する必要があり、注文列でノードを並べる必要があります。 たとえば、ノード番号3と4の順序値を入れ替えると、それらを同じ場所(親ノード2の下)に表示したいが、ノード4が最初に表示される。 "ORDER BY path、order"は使用できません。パスは一意であり、常にorder列を上書きするためです。 parent_pathという名前の列をもう1つ追加しようとしましたが、これは親へのパスのみを保持し、 "ORDER BY parent_path、order"で順序付けしますが、これはレベルがグループ化されているので間違っていることが判明しました(最初に、レベルノード、次にすべての第2レベルノードなど)。

私の目標は、ツリー構造を正しく取得することです(子供は親の下にあり、次にID列でもソートされます)。もちろん、再帰を使用して多くのクエリで構造体を取得することはできますが、orderカラムを使用せずに1つのクエリを使用して行うことができる場合は、オーダリングでも1つのクエリでこれを行う方法があると思います。私はデータベースにもっと熟練した誰かが方法を見つけるかもしれないと確信しています。

私はこれをかなりの時間、グーグルで探していますが、誰もその問題を抱えていないようです。誰もが再帰的に多くのクエリを使用して解決しますが、DBが非常に大きくなり、深さのレベルが多く、ツリーを非常に頻繁に生成する必要があります。私は再帰がDBに不必要な負担として見えます。

ご迷惑をおかけして申し訳ありませんが、私はいくつかの基本的かつ明白な解決策が欠けています。

は、あなたが何ができるか、 ヤクブ

+0

私の答えはこちらを見てください:[ソートツリーとマテリアライズドパス](http://stackoverflow.com/a/2797724/39430) – RedFilter

+0

@RedFilter私はあなたの答えを見ましたが、わかりませんわかりました。どうやらあなたの解決策としての私のせいでそこで働いたが、私は私のケースでどうやって使うのかをすぐに説明できますか?どうもありがとう。 – Jakub

答えて

1

ありがとうSortPath列を作成することです。通常これは名前のようなものですが、あなたの場合はOrder列を使用します。これはパスの列に似ていますが、node_id番号は注文番号に置き換えられます。

私はこの回答でそれを行う方法の例を与えました:https://stackoverflow.com/a/2797724/39430

+0

ノードフィールド内で一意にする必要はないので、orderフィールドのみからのSortpathは良い考えではないかもしれませんが、私は別のものに私を影響させました - 私はfullpathをとり、.nodeIdをrepalcingすることによってsortpathを作成しました。 .order-nodeId。はうまく動作します。オーダーと親の両方を尊重します。唯一の欠点は、親ノードの鉱石設定が変更されたときに、そのツリーの下にあるすべてのノードを再帰的に再計算する必要があることです。しかし、はい、ありがとう、それはそれについて考える正しい方法でした。私は答えを受け入れる、ありがとう。 – Jakub

+0

@Jakubあなたは当然ですが、私はあなたの事を完全には考えていませんでした。 – RedFilter

関連する問題