トップページに戻る    次のSQLパズルへ    前のSQLパズルへ

8-25 Oracle9iで、connect_by_rootを模倣

SQLパズル

Busyoテーブル
name      oya       采配
--------  --------  ----
織田信秀  null        78
織田信長  織田信秀    95
織田信行  織田信秀    43
織田信忠  織田信長    70
織田信考  織田信長    56
織田秀信  織田信忠    31
徳川家康  null        97
徳川秀忠  徳川家康    71
松平忠吉  徳川家康    68
徳川家光  徳川秀忠    84

Oracle9iで、connect_by_rootを模倣し、
木の根のデータ(采配)も出力する。

出力結果
name      oya       采配  root采配
--------  --------  ----  --------
織田信秀  null        78        78
織田信長  織田信秀    95        78
織田信行  織田信秀    43        78
織田信忠  織田信長    70        78
織田信考  織田信長    56        78
織田秀信  織田信忠    31        78
徳川家康  null        97        97
徳川秀忠  徳川家康    71        97
松平忠吉  徳川家康    68        97
徳川家光  徳川秀忠    84        97


データ作成スクリプト

create table Busyo(name,oya,采配) as
select '織田信秀',null      ,78 from dual union
select '織田信長','織田信秀',95 from dual union
select '織田信行','織田信秀',43 from dual union
select '織田信忠','織田信長',70 from dual union
select '織田信考','織田信長',56 from dual union
select '織田秀信','織田信忠',31 from dual union
select '徳川家康',null      ,97 from dual union
select '徳川秀忠','徳川家康',71 from dual union
select '松平忠吉','徳川家康',68 from dual union
select '徳川家光','徳川秀忠',84 from dual;


SQL

--■■■connect_by_rootを使う方法(10g以降)■■■
select name,oya,采配,connect_by_root 采配 as root采配
  from Busyo
Start With oya is null
connect by prior name = oya;

--■■■sys_connect_by_pathを使う方法■■■
select name,oya,采配,
to_number(substr(sys_connect_by_path(to_char(采配),','),2,
                      decode(instr(substr(sys_connect_by_path(to_char(采配),','),2),','),
                             0,Length(substr(sys_connect_by_path(to_char(采配),','),2)),
                             instr(substr(sys_connect_by_path(to_char(采配),','),2),',')-1))) as Root采配
  from Busyo
Start With oya is null
connect by prior name = oya;

--■■■8iEEでも動きそうな方法■■■
select name,oya,采配,
First_Value(采配) over(partition by PartID order by SortKey) as Root采配
from (select name,oya,采配,SortKey,
      sum(willSum) over(order by SortKey) as PartID
      from (select name,oya,采配,decode(Level,1,1,0) as willSum,
            RowNum as SortKey
              from Busyo
            Start With oya is null
            connect by prior name = oya));


解説

10gなら、connect_by_rootを使うとシンプルですが、
9iなら使い分けるといいでしょう。

4-9 階層問い合わせの根を取得
7-27 階層問い合わせの根と葉を取得
8-43 Oracle9iでnocycleを模倣
9-15 階層問い合わせの根と葉も出力
10-149 Oracle9iでconnect_by_isleafを模倣