3

階層データのクエリについてサポートが必要です。これは単一の単純なテーブルであり、ルートエントリの場合はnullになる可能性がありますparent_idid

  create table edition (
      id           NUMBER(20),
      parent_id    NUMBER(20)
  );

テーブル内の各レコードについて、最大IDを持つ最も深い子を見つける必要があります。レコードに子がない場合は、独自のIDを返す必要があります。私は自分で試しましたがSTART WITH A.id = B.id、AとBがサブクエリである場合は使用できませんでした。これは、Oracleがそのような結合を許可していないようです。

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

     id      parent_id
   ----------------------
      1        NULL
      2           1
      3           1
      4           1
      5           4
      6           5
      7           5

およびサンプル結果

     id      result
   ----------------------
      1           7
      2           2
      3           3
      4           7
      5           7
      6           6
      7           7
4

2 に答える 2

5

やってみたいと思います

create table tq84_edition (
  id        number primary key,
  parent_id number references tq84_edition
);

insert into tq84_edition values (  1, null);
insert into tq84_edition values (  2,    1);
insert into tq84_edition values (  3,    1);
insert into tq84_edition values (  4,    1);
insert into tq84_edition values (  5,    4);
insert into tq84_edition values (  6,    5);
insert into tq84_edition values (  7,    5);


with x (root, id, parent_id, lvl) as (
               select id    root,
                      id,
                      parent_id,
                      1 lvl
                from  tq84_edition
        UNION ALL
               select x.root  root,
                      tq84_edition.id,
                      tq84_edition.parent_id,
                      x.lvl + 1 lvl
                 from x,
                      tq84_edition
                where x.id = tq84_edition.parent_id
)
select  root, max(id) keep (dense_rank last order by lvl, id)
  from x
 group by root;
于 2012-08-16T12:26:04.970 に答える
4

私が考えることができる別のアプローチは、他のRDBMSに移植する方が簡単です:http ://www.sqlfiddle.com/#!4 / da0a3 / 19

with parent(root_node, child_of, parent_id, depth)  as
(
  select id, id, parent_id, 1
  from edition
  union all
  select p.root_node, e.id, e.parent_id, p.depth + 1
  from edition e
  join parent p on p.child_of = e.parent_id
)
select root_node, max(child_of)
from parent
where (root_node,depth) in
     (select root_node,max(depth) from parent group by root_node)
group by root_node
order by root_node

出力:

| ROOT_NODE | MAX(CHILD_OF) |
-----------------------------
|         1 |             7 |
|         2 |             2 |
|         3 |             3 |
|         4 |             7 |
|         5 |             7 |
|         6 |             6 |
|         7 |             7 |

今、私はOracle(およびhttp://sqlfiddle.comも)が大好きです。非常に簡潔です。これで、KEEPDENSE_RANKでのMINとMAXの使用法がわかりました。以前は、KEEPDENSE_RANKでMIN/MAXを明示的に指定するユーティリティはありませんでした。これでユーティリティがあることがわかりました。深さに関係がある場合は、MINとMAXを使用して、関係の最初と最後が誰であるかを確認できます。

例:http ://www.sqlfiddle.com/#!4 / da0a3 / 24

with parent(root_node, child_of, parent_id, depth)  as
(
  select id, id, parent_id, 1
  from edition
  union all
  select p.root_node, e.id, e.parent_id, p.depth + 1
  from edition e
  join parent p on p.child_of = e.parent_id
)
select root_node, 

  min(child_of) keep(dense_rank last order by depth) as first_in_deepest,
  max(child_of) keep(dense_rank last order by depth) as last_in_deepest

from parent
group by root_node;






| ROOT_NODE | FIRST_IN_DEEPEST | LAST_IN_DEEPEST |
--------------------------------------------------
|         1 |                6 |               7 |
|         2 |                2 |               2 |
|         3 |                3 |               3 |
|         4 |                6 |               7 |
|         5 |                6 |               7 |
|         6 |                6 |               6 |
|         7 |                7 |               7 |
于 2012-08-16T12:57:02.867 に答える