那些不是层次结构;它们是有向图。您仍然可以在 Oracle 中使用 CONNECT BY 来处理它们,但如果没有 START WITH 的根节点,如果您的数据集很大,性能可能会出现问题。
无论如何,你需要做的是CONNECT BY NOCYCLE 没有START WITH。这将从每个单独的节点开始计算一棵树。然后,获取每个节点的 CONNECT_BY_ROOT 并获取每个不同节点值的 MIN()。
这是一个带有数据的工作示例。它比它需要的更复杂,因为没有地方可以获得所有节点的完整列表,所以你必须将每个顶点分成两行(一个有 from_node,一个有 to_node)以确保你包括全部。
CREATE TABLE tbl_tst ( from_node VARCHAR2(1), to_node VARCHAR2(1) );
INSERT INTO tbl_tst VALUES ( 'a', 'b');
INSERT INTO tbl_tst VALUES ( 'b', 'c');
INSERT INTO tbl_tst VALUES ( 'b', 'd');
INSERT INTO tbl_tst VALUES ( 'd', 'a');
INSERT INTO tbl_tst VALUES ( 'd', 'e');
INSERT INTO tbl_tst VALUES ( 'f', 'g');
INSERT INTO tbl_tst VALUES ( 'g', 'h');
INSERT INTO tbl_tst VALUES ( 'h', 'f');
INSERT INTO tbl_tst VALUES ( 'i', 'j');
COMMIT;
WITH groups AS (
SELECT DISTINCT
tt.from_node,
tt.to_node,
MIN(CONNECT_BY_ROOT(from_node))
OVER ( PARTITION BY tt.from_node) group_min
FROM tbl_tst tt
CONNECT BY NOCYCLE from_node = PRIOR to_node
OR to_node = PRIOR from_node
)
SELECT DENSE_RANK() OVER ( ORDER BY group_min ) group_number,
DECODE(splitter.rn,1,groups.from_node,2,groups.to_node) node
FROM groups
CROSS JOIN ( SELECT rownum rn FROM dual CONNECT BY rownum <= 2 ) splitter
GROUP BY DECODE(splitter.rn,1,groups.from_node,2,groups.to_node),
group_min
ORDER BY group_min, node;
+--------------+------+
| GROUP_NUMBER | NODE |
+--------------+------+
| 1 | a |
| 1 | b |
| 1 | c |
| 1 | d |
| 1 | e |
| 2 | f |
| 2 | g |
| 2 | h |
| 3 | i |
| 3 | j |
+--------------+------+