1

私の日付はツリー構造で構成されています。

以下が適用されます(Oracle SQL構文)。

CREATE TABLE TREE
(
  NAME VARCHAR2(20),
  ID NUMBER(10, 0),
  PARENT NUMBER(10, 0)
)
;

INSERT INTO "TREE" (NAME, ID) VALUES ('a', '1');
INSERT INTO "TREE" (NAME, ID, PARENT) VALUES ('a.1', '2', '1');
INSERT INTO "TREE" (NAME, ID, PARENT) VALUES ('a.2', '3', '1');
INSERT INTO "TREE" (NAME, ID, PARENT) VALUES ('a.2.1', '4', '3');
INSERT INTO "TREE" (NAME, ID, PARENT) VALUES ('a.2.2', '5', '3');
INSERT INTO "TREE" (NAME, ID) VALUES ('b', '6');

IDで完全なツリーを返したいので、クエリの場合:

select name, id <<<TODO LOGIC>> where id = 1

私は得るだろう

|  name  |  id  |
|  a     |  1   |
|  a.1   |  2   |
|  a.2   |  3   |
|  a.2.1 |  4   |
|  a.2.2 |  5   |

サブツリーの場合、次のようになります。

select name, id <<<TODO LOGIC>> where id = 3

私は得るだろう

|  name  |  id  |
|  a.2   |  3   |
|  a.2.1 |  4   |
|  a.2.2 |  5   |

一方、フラットエントリbの場合、次のようになります。

select name, id <<<TODO LOGIC>> where id = 6

私は得るだろう

|  name  |  id  |
|  b     |  6   |

単純な省略された結合クエリはこの目的を達成できないようです、または私は何かを逃していますか?

次のクエリは完全な構造を返しますが、 whereステートメントでフィルタリングを開始すると失敗します。

select t1.id t1Id, t2.id t2Id, t1.name t1Name, t2.name t2Name from tree t1 left outer join tree t2 on t1.id = t2.parent
4

3 に答える 3

3

ツリー構造の場合、階層クエリが必要になる可能性があります。ここにあります:

 select t.*
   from tree t
connect by prior t.id = t.parent
  start with t.id = :id
  order siblings by t.id

詳細については、階層クエリを参照してください。

于 2009-11-23T11:44:42.770 に答える
2

Oracleでは、startwith-connectby構文を使用できます。間違えなければこんな感じ

select * from Tree t
start with t.ID = 1 connect by prior t.ID = t.Parent

しかし、私にはすぐにチェックするOracleがありません。多分そのprior t.Parent = t.ID。時々遅くなる可能性があることに注意してください、注意して使用してください。

別の方法は、ノード間のすべての間接的な関係(aa.1だけでなく、aa.2.1など)を格納するテーブルを作成することです。PL/SQL再帰ストアドプロシージャを使用して入力できます。ふたつのやり方:

  1. 簡単な方法は、間接テーブルの完全な補充を行う手順を作成することです。レポートを実行する前に呼び出すことができます。

  2. インスタントエフェクトが必要な場合は、ツリー内の1つのレコードに対してのみ間接的な関係を更新するように、補充手順を作成する必要があります。次に、Treeへの直接の挿入と更新を禁止し、保存されたPL / SQLプロシージャ(InsertTree / UpdateTreeなど)を経由するように強制します。これにより、プロシージャが呼び出され、間接的な関係でテーブルが更新されます。

于 2009-11-23T11:07:10.697 に答える
0

これに使用できunion、1つのクエリで選択できるように、ツリーの深さを制限する必要があります。

SELECT id, name
FROM TREE as node
WHERE 
  node.id = :id
UNION
SELECT child1.id, child1.name
FROM TREE as node
  inner join TREE as child1 on node.id = child1.parent
WHERE 
  node.id = :id
UNION
SELECT child2.id, child2.name
FROM TREE as node
  inner join TREE as child1 on node.id = child1.parent
  inner join TREE as child2 on child1.id = child2.parent
WHERE 
  node.id = :id

ここでの問題は、SQLは再帰的に非常に悪いことです(リレーショナル構造は実際にはこれで優れています)。

完全に動的にするには、ツリーの各レベルに対してクエリを使用するか、使用可能なものがある場合はデータベースエンジン固有のSQL拡張機能を使用します。

于 2009-11-23T11:02:02.923 に答える