2

いくつかの階層データを表す(大きな)Oracle9テーブルをクエリしようとしています。親アイテムには、親IDとして独自のIDがあります。例として;

ID    PARENTID               
----- --------  
1     1
2     1
3     2
4     2
5     3
6     6
7     6
8     6
9     4
10    10

各IDと、そのIDの最終的な親を返すクエリが必要なので、例を続けます

ID    UlitimateParent
----  ----
1     1
2     1
3     1
4     1
5     1
6     6
7     6
8     6
9     1
10    10

Connect Byを使用したいくつかの例を見てきましたが、これを機能させることができないようです。何か案は ?

4

2 に答える 2

3

10g+ では、次のCONNECT_BY_ROOT関数を使用します。

SQL> with data as (
  2     SELECT 1 id, 1 parent_id FROM DUAL
  3     UNION ALL SELECT 2 , 1  FROM DUAL
  4     UNION ALL SELECT 3 , 2  FROM DUAL
  5     UNION ALL SELECT 4 , 2  FROM DUAL
  6     UNION ALL SELECT 5 , 3  FROM DUAL
  7     UNION ALL SELECT 6 , 6  FROM DUAL
  8     UNION ALL SELECT 7 , 6  FROM DUAL
  9     UNION ALL SELECT 8 , 6  FROM DUAL
 10     UNION ALL SELECT 9 , 4  FROM DUAL
 11     UNION ALL SELECT 10, 10 FROM DUAL
 12  )
 13  SELECT id, connect_by_root(id) ultimate_parent_id
 14    FROM data
 15  START WITH id = parent_id
 16  CONNECT BY parent_id = PRIOR id AND id != PRIOR id  ;

ID  ULTIMATE_PARENT_ID
--- ------------------
  1                  1
  2                  1
  3                  1
  5                  1
  4                  1
  9                  1
  6                  6
  7                  6
  8                  6
 10                 10

SYS_CONNECT_BY_PATH9i では、 (適切な部分文字列を使用して) 次を使用できます。

SQL> with data as (
  2     SELECT 1 id, 1 parent_id FROM DUAL
  3     UNION ALL SELECT 2 , 1  FROM DUAL
  4     UNION ALL SELECT 3 , 2  FROM DUAL
  5     UNION ALL SELECT 4 , 2  FROM DUAL
  6     UNION ALL SELECT 5 , 3  FROM DUAL
  7     UNION ALL SELECT 6 , 6  FROM DUAL
  8     UNION ALL SELECT 7 , 6  FROM DUAL
  9     UNION ALL SELECT 8 , 6  FROM DUAL
 10     UNION ALL SELECT 9 , 4  FROM DUAL
 11     UNION ALL SELECT 10, 10 FROM DUAL
 12  )
 13  SELECT id, sys_connect_by_path(id, '->') path
 14    FROM data
 15  START WITH id = parent_id
 16  CONNECT BY parent_id = PRIOR id
 17         AND id != PRIOR id;

        ID PATH
---------- --------------------
         1 ->1
         2 ->1->2
         3 ->1->2->3
         5 ->1->2->3->5
         4 ->1->2->4
         9 ->1->2->4->9
         6 ->6
         7 ->6->7
         8 ->6->8
        10 ->10
于 2012-10-05T15:12:02.537 に答える
2

あなたの質問のおかげで、私はこれを学びました:)

あなたが使うことができます

replace(sys_connect_by_path(decode(level, 1, id), '~'), '~')

10gより前のconnect_by_root関数を置き換えます。

with data1 as (
   SELECT 1 id, 1 parent_id FROM DUAL
   UNION ALL SELECT 2 , 1  FROM DUAL
   UNION ALL SELECT 3 , 2  FROM DUAL
   UNION ALL SELECT 4 , 2  FROM DUAL
   UNION ALL SELECT 5 , 3  FROM DUAL
   UNION ALL SELECT 6 , 6  FROM DUAL
   UNION ALL SELECT 7 , 6  FROM DUAL
   UNION ALL SELECT 8 , 6  FROM DUAL
   UNION ALL SELECT 9 , 4  FROM DUAL
   UNION ALL SELECT 10, 10 FROM DUAL
) 
SELECT id, replace(sys_connect_by_path(decode(level,
                                               1, id), '~'), '~') 
            ultimate_parent_id
  FROM data1
  START WITH id = parent_id
  CONNECT BY parent_id = PRIOR id AND id != PRIOR id  ;

ID      PATH
--------------
1   1
2   1
3   1
5   1
4   1
9   1
6   6
7   6
8   6
10  10
于 2012-10-05T15:22:12.403 に答える