2

我正在尝试查询代表一些分层数据的(大)Oracle 9 表。父项有自己的 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

在 9i 中,您可以使用SYS_CONNECT_BY_PATH(带有适当的子字符串):

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 回答