2010-12-03 23 views
13

Mysqlの再帰?

 folders_table 
    ----------------------- 
     INT id_folder 
     INT id_folder_parent 
     VARCHAR folder_name 

単純なディレクトリ構造を格納しています。 1つのSELECTクエリでディレクトリのすべてのサブディレクトリを取得するにはどうすればよいですか?

+0

なぜアプリケーションレベルではなくdbレベルでこれをやりたいのですか? – papdel

+6

1つのクエリは、アプリケーションレベルでツリーを構築するのに必要な多くのクエリよりもはるかに高速であるためです。 –

+0

あなたはクエリから探している正確な結果は何ですか?指定された単一のディレクトリのサブディレクトリが必要ですか?あなたはすべてのディレクトリとそのすべてのサブディレクトリのペアをリストにしたいですか?クエリを使用してツリー構造を構築しますか?他に何か? – outis

答えて

17

をサポートしていないとしてあなたが示されたテーブル構造で

+0

サイトポイントリンクが壊れています。あなたはそれの別のコピーを見つける場所を知っていますか? – Cam

+0

もう一度戻るようです。 –

+0

申し訳ありませんが、私はMySQLの記事を意味しました。あなたはそのコピーをどこに見つけるか知っていますか? – Cam

3

、これは、MySQLで行うことができないことは可能ですが、あなたはあなたのデータベース構造を変更する必要があります。変更が行われると、1つのクエリで任意の深度のツリーを取得できます。クエリは少し複雑ですが、それはまだかなり簡単です。

+0

下記のコメントを参照してください。このデータ構造では不可能ですが、再帰を避け、データ構造を少し変更することで可能です。 –

+1

これは私が言ったことです;)再帰的なクエリはMySQLでは(他のDBMSとは異なり)できません –

+0

しかし、これはmysqlで行うことができます。 OPは、再帰的なクエリで完了しなければならないとは決して言わなかった。私が指摘しているアプローチは、1つのクエリでそれを行います。 –

0

は、MySQL/MariaDBを使えば、あなたが関係、基本的にPARENTIDとたchildIDを置く特別なテーブルを作成することができますmysqlのプラグインですオープンクエリグラフエンジン(http://openquery.com/graph/doc)を使用することができます。

魔法は、クエリに渡される値に応じて特別な列ラッチを使用してこのテーブルをクエリすることで、実行するコマンドをOQGRAPHエンジンに伝えます。詳細については、ドキュメントを参照してください。

ツリー(再帰的な1-n関係)だけでなく、重み付きグラフデータ構造(再帰的nm関係)も扱います(例えば、企業の所有権を保存したいと考えている企業は複数の子会社を持つことができます。いくつかの株主)。

0

もう1つの選択肢は、ノードの深さと、各ノードの完全なパスの識別子を保持し、これらの両方を基準として使用することです。

私は、リレーショナルデータベースにXMLノードを格納する方法は以下の通りです:この例では

SELECT id,value FROM element e1 
INNER JOIN element e2 ON (e2.id=e1.parent_id AND name='friend') 
WHERE e1.depth>4 AND e1.path like 'root[1]/users[1]/user:dana[1]/public[1]%' 

、私は、ノード名のフィールドとで重複ノードのために角括弧内interatorを持っていますツリーの各レベルで同じノード名。

各ノードを挿入するときには、パスの深さを保存すると同時に、ルートノード(parent_id IS NULL)まで親を追従させて、各レベルを配列に追加してフルパスを計算する必要があります。

データベースに格納されているどのような種類の階層でも視覚的に表現でき、すべてのリクエストにツリーが表示されるため、すべてのパスに簡単にアクセスできます。特に、直接的な再帰性を持たないmysql SQL構文。

階層内にノードを格納する左/右スキーム(ネストされたセット隣接リスト)は、私の心では危険です。このようなスキームでは、管理が非常に複雑なため、ずっと多くのことが間違っています。

0

1、新しいテーブルを作成します。 tree_folder(id, id_folder, tree_id) 2、新しいテーブルを作成します。 tree(id, tree_json)

テーブルtreeテーブル全体がツリーノードを維持します。たとえば、ルートノードが1の次のツリー。

{ 
    "folder_id": 1, 
    "parent_folder_id": 0, 
    "children": [ 
     { 
      "folder_id": 10, 
      "parent_folder_id": 1, 
      "children": null 
     }, 
     { 
      "folder_id": 11, 
      "parent_folder_id": 2, 
      "children": null 
     } 
    ] 
} 

表にはこの行が含まれています。

[id, tree_json] 
[1, "xxxxx"] 

次に、ノードとツリーの関係を維持します。ご覧のとおり、ツリーにはノード11011が含まれています。次にテーブルtree_folderがあります。

[id, folder_id, tree_id] 
[1, 1  , 1] 
[2, 10  , 1] 
[3, 11  , 1] 

10のツリーを取得する必要がある場合。ただ木から手に入れて、プログラムでそれを扱いなさい。

このように、mysqlの代わりにメモリ内で再帰を行うだけです。

データを書き込むときに構造を維持する必要がありますが、クエリは簡単で高速です。クエリが頻繁である場合、これは正常に動作します。しかし、書き込みが頻繁な場合は、このメソッドの代わりにキャッシュを使用してください。