4

ツリー構造が次のようにSQLに実装されているとします。

CREATE TABLE nodes (
    id INTEGER PRIMARY KEY,
    parent INTEGER -- references nodes(id)
);

この表現でサイクルを作成することはできますが、それを決して起こさせないと仮定しましょう。このテーブルには、ルート(親がnullのレコード)とその子孫のコレクションのみが格納されます。

目標は、テーブル上のノードのIDを指定して、その子孫であるすべてのノードを見つけることです。

Aの親がBであるか、Aの親がBの子孫ある場合AはBの子孫です。再帰的定義に注意してください。

サンプルデータは次のとおりです。

INSERT INTO nodes VALUES (1, NULL);
INSERT INTO nodes VALUES (2, 1);
INSERT INTO nodes VALUES (3, 2);
INSERT INTO nodes VALUES (4, 3);
INSERT INTO nodes VALUES (5, 3);
INSERT INTO nodes VALUES (6, 2);

これは以下を表します:

1
`-- 2
    |-- 3
    |   |-- 4
    |   `-- 5
    |
    `-- 6

これを行うことで、の(直接の)子を選択できます1

SELECT a.* FROM nodes AS a WHERE parent=1;

これを行うことで、の子と孫を選択できます1

SELECT a.* FROM nodes AS a WHERE parent=1
UNION ALL
SELECT b.* FROM nodes AS a, nodes AS b WHERE a.parent=1 AND b.parent=a.id;

これを行うことで、の子供、孫、および曽孫を選択できます1

SELECT a.* FROM nodes AS a WHERE parent=1
UNION ALL
SELECT b.* FROM nodes AS a, nodes AS b WHERE a.parent=1 AND b.parent=a.id
UNION ALL
SELECT c.* FROM nodes AS a, nodes AS b, nodes AS c WHERE a.parent=1 AND b.parent=a.id AND c.parent=b.id;

1固定の深さではなく、ノードのすべての子孫を取得するクエリをどのように構築できますか?再帰クエリなどを作成する必要があるようです。

SQLiteを使用してそのようなクエリが可能かどうか知りたいのですが。ただし、このタイプのクエリでSQLiteで使用できない機能が必要な場合は、他のSQLデータベースで実行できるかどうかを知りたいと思います。

4

3 に答える 3

9

一部のデータベースでは、再帰的な共通テーブル式を使用できますが、SQLiteは使用できません。

テーブル定義の変更を検討できます。このようなテーブルを使用すると、1のすべての子孫を簡単に照会できます。

id (varchar)
--------------
001
001002
001002003
001002003004
001002003005
001002006

これにより、次のように1のすべての子孫を照会できます。

SELECT * FROM YourTable WHERE id LIKE '001%'

少し風変わりに聞こえますが、実際には非常にうまく機能します。

于 2010-04-30T04:21:03.130 に答える
6

スキーマを設定する方法は、(あなたが発見したように)リレーショナルモデルにはあま​​り適していません。しかし、最初はそれほど明白ではないかもしれませんが、はるかに柔軟な別の方法があります。これは「入れ子集合モデル」と呼ばれ、構造が少し異なります。

MySQLでの階層データの管理(「入れ子集合モデル」のセクションを探してください)は、MySQLでこれを行う方法を示していますが、SQLiteにかなり簡単に変換できるはずです。その記事は実際にはかなり長いので、ここではあまり詳しく説明しませんが、それはあなたが始めるために必要なすべてをあなたに与えるはずです。

于 2010-04-30T04:16:13.510 に答える
1

Oracleには、これに使用できるCONNECT BY構文がありますが、もちろん、これはoracleに固有のものです。

于 2010-04-30T04:20:57.170 に答える