ファイルシステム内のディレクトリの階層/ツリーデータベース

hierarchical-data sql sqlite tree
ファイルシステム内のディレクトリの階層/ツリーデータベース

階層/ツリー構造を維持したまま、ディスクに存在するディレクトリをデータベースに保存したい。

ここにイチジク、

                         (ROOT)
                       /        \
                    Dir2        Dir3
                   /    \           \
                 Dir4   Dir5        Dir6
                 /
               Dir7
  • SQLite *データベースを使用しています。

  • 上記の構造をSQLiteに保存するためのSQLクエリを提案してください
    データベース。

  • および1つを選択すると、ディレクトリの完全なパスを取得するクエリ。

i.e. Dir6を選択すると、ROOT / Dir2 / dir3 / dir7のようなフルパスを取得できると仮定します。

  28  21


ベストアンサー

SQLiteのクイッククロージャーテーブルの例を次に示します。 既存のツリーにアイテムを挿入するためのステートメントは含めていません。 代わりに、ステートメントを手動で作成しました。 insertおよびdeleteステートメントは、http://www.slideshare.net/billkarwin/models-for-hierarchical-data [階層データのモデル]スライドで見つけることができます。

ディレクトリのIDを挿入するときの健全性のために、ディレクトリのIDに一致するようにディレクトリの名前を変更しました。

        (ROOT)
      /        \
    Dir2        Dir3
    /    \           \
  Dir4   Dir5        Dir6
  /
Dir7

テーブルを作成

CREATE TABLE `filesystem` (
  `id` INTEGER,
  `dirname` TEXT,
  PRIMARY KEY (`id`)
);

CREATE TABLE `tree_path` (
  `ancestor` INTEGER,
  `descendant` INTEGER,
  PRIMARY KEY (`ancestor`, `descendant`)
);
  • `filesystem`テーブルにディレクトリを挿入します*

INSERT INTO filesystem (id, dirname) VALUES (1, 'ROOT');
INSERT INTO filesystem (id, dirname) VALUES (2, 'Dir2');
INSERT INTO filesystem (id, dirname) VALUES (3, 'Dir3');
INSERT INTO filesystem (id, dirname) VALUES (4, 'Dir4');
INSERT INTO filesystem (id, dirname) VALUES (5, 'Dir5');
INSERT INTO filesystem (id, dirname) VALUES (6, 'Dir6');
INSERT INTO filesystem (id, dirname) VALUES (7, 'Dir7');

クロージャーテーブルパスを作成

INSERT INTO tree_path (ancestor, descendant) VALUES (1, 1);
INSERT INTO tree_path (ancestor, descendant) VALUES (1, 2);
INSERT INTO tree_path (ancestor, descendant) VALUES (1, 3);
INSERT INTO tree_path (ancestor, descendant) VALUES (1, 4);
INSERT INTO tree_path (ancestor, descendant) VALUES (1, 5);
INSERT INTO tree_path (ancestor, descendant) VALUES (1, 6);
INSERT INTO tree_path (ancestor, descendant) VALUES (1, 7);
INSERT INTO tree_path (ancestor, descendant) VALUES (2, 2);
INSERT INTO tree_path (ancestor, descendant) VALUES (2, 4);
INSERT INTO tree_path (ancestor, descendant) VALUES (2, 5);
INSERT INTO tree_path (ancestor, descendant) VALUES (2, 7);
INSERT INTO tree_path (ancestor, descendant) VALUES (3, 3);
INSERT INTO tree_path (ancestor, descendant) VALUES (3, 6);
INSERT INTO tree_path (ancestor, descendant) VALUES (4, 4);
INSERT INTO tree_path (ancestor, descendant) VALUES (4, 7);
INSERT INTO tree_path (ancestor, descendant) VALUES (5, 5);
INSERT INTO tree_path (ancestor, descendant) VALUES (6, 6);
INSERT INTO tree_path (ancestor, descendant) VALUES (7, 7);

いくつかのクエリを実行

# (ROOT) and subdirectories
SELECT f.id, f.dirname FROM filesystem f
  JOIN tree_path t
    ON t.descendant = f.id
 WHERE t.ancestor = 1;

+----+---------+
| id | dirname |
+----+---------+
|  1 | ROOT    |
|  2 | Dir2    |
|  3 | Dir3    |
|  4 | Dir4    |
|  5 | Dir5    |
|  6 | Dir6    |
|  7 | Dir7    |
+----+---------+


# Dir3 and subdirectories
SELECT f.id, f.dirname
  FROM filesystem f
  JOIN tree_path t
    ON t.descendant = f.id
 WHERE t.ancestor = 3;

+----+---------+
| id | dirname |
+----+---------+
|  3 | Dir3    |
|  6 | Dir6    |
+----+---------+

# Dir5 and parent directories
SELECT f.id, f.dirname
  FROM filesystem f
  JOIN tree_path t
    ON t.ancestor = f.id
 WHERE t.descendant = 5;

+----+---------+
| id | dirname |
+----+---------+
|  1 | ROOT    |
|  2 | Dir2    |
|  5 | Dir5    |
+----+---------+

# Dir7 and parent directories
SELECT f.id, f.dirname
  FROM filesystem f
  JOIN tree_path t
    ON t.ancestor = f.id
 WHERE t.descendant = 7;

+----+---------+
| id | dirname |
+----+---------+
|  1 | ROOT    |
|  2 | Dir2    |
|  4 | Dir4    |
|  7 | Dir7    |
+----+---------+

SELECT f.id, f.dirname
  FROM filesystem f
  JOIN tree_path t
    ON t.ancestor = f.id
 WHERE t.descendant = (
SELECT id
  FROM filesystem
 WHERE dirname LIKE '%7%'
);

+----+---------+
| id | dirname |
+----+---------+
|  1 | ROOT    |
|  2 | Dir2    |
|  4 | Dir4    |
|  7 | Dir7    |
+----+---------+

35


階層データは、それぞれがIDと親IDを持つ一連のノードとして表します。 2つのID列と個別のディレクトリ名のテキスト用の1つの列を持つDIRTABというテーブルに保存できます。

ID -- as a primary key
PARENT_ID -- refers to the ID of the parent row in DIRTAB
DIRNAME -- the text of the name eg Dir5

SQLiteには、Oracleが階層データを処理する必要があるCONNECT BY句がありませんが、butいSQLを受け入れる準備ができている場合、階層的な何かに近づけることができると思います。

SELECT (CASE WHEN p5.DIRNAME IS NOT NULL THEN p5.DIRNAME || '/' ELSE '' END) ||
       (CASE WHEN p4.DIRNAME IS NOT NULL THEN p4.DIRNAME || '/' ELSE '' END) ||
       (CASE WHEN p3.DIRNAME IS NOT NULL THEN p3.DIRNAME || '/' ELSE '' END) ||
       (CASE WHEN p2.DIRNAME IS NOT NULL THEN p2.DIRNAME || '/' ELSE '' END) ||
       (CASE WHEN p1.DIRNAME IS NOT NULL THEN p1.DIRNAME || '/' ELSE '' END) ||
       p0.DIRNAME as FULLPATH
FROM DIRTAB p0
     LEFT OUTER JOIN DIRTAB p1 ON p1.ID = p0.PARENT_ID
     LEFT OUTER JOIN DIRTAB p2 ON p2.ID = p1.PARENT_ID
     LEFT OUTER JOIN DIRTAB p3 ON p3.ID = p2.PARENT_ID
     LEFT OUTER JOIN DIRTAB p4 ON p4.ID = p3.PARENT_ID
     LEFT OUTER JOIN DIRTAB p5 ON p5.ID = p4.PARENT_ID
WHERE p0.DIRNAME = 'Dir6'

ここでの問題は、ディレクトリ構造の最大の深さを予測し、対処するためにSQLステートメントを拡張する必要があることです。 例として6つのレベルを実行しました。 +また、SQLiteには空の文字列の連結に問題がないと仮定しています。 (一部のDBはそれらをヌルとして扱い、式の結果全体をヌルに変換します)

1


  • Modified Preorder Tree Traversal *:http://www.sitepoint.com/hierarchical-data-database/の方法を読んでください。

このリンクでは、リレーショナルデータベースに階層データを保存する2つの方法について説明します。隣接リストモデルと修正された事前順序ツリートラバーサルアルゴリズムです。

Modified Preorder Tree Traversalメソッドの主なアイデアは、ナビゲーションとサブツリーの選択を補助するためのポインターですべてのノードに注釈を付けることです:https://i.stack.imgur.com/6tWh9.jpg[image:https://i.stack .imgur.com / 6tWh9.jpg [ここに画像の説明を入力]]

1


タイトルとURLをコピーしました