Рекурсивный CTE (это для Postgres, будут необходимы незначительные изменения для Oracle) Примечание: без контрмер, некоторые петли не избежать, что приводит к бесконечной рекурсии.
CREATE TABLE pairs
(e1 varchar NOT NULL
, e2 varchar NOT NULL
, PRIMARY KEY (e1,e2)
);
INSERT INTO pairs(e1,e2) VALUES
('A' , 'B')
, ('B','C')
, ('C','D')
, ('C','G')
, ('E','F')
, ('I','E')
, ('H','G')
, ('J','K')
, ('K','L')
;
WITH RECURSIVE tree AS (
WITH dpairs AS (
SELECT e1 AS one, e2 AS two FROM pairs WHERE e1 < e2
UNION ALL
SELECT e2 AS one, e1 AS two FROM pairs WHERE e1 > e2
)
SELECT dp.one AS opa
, dp.one AS one
, dp.two AS two
FROM dpairs dp
WHERE NOT EXISTS (SELECT *
FROM dpairs nx
WHERE nx.two = dp.one
AND nx.one < dp.one
)
UNION ALL
SELECT tr.opa AS opa
, dp.one AS one
, dp.two AS two
FROM tree tr
JOIN dpairs dp ON dp.one = tr.two AND dp.two <> tr.opa AND dp.two <> tr.one
)
SELECT opa,one,two
, dense_rank() OVER (ORDER BY opa) AS rnk
FROM tree
ORDER BY opa, one,two
;
Результат:
opa | one | two | rnk
-----+-----+-----+-----
A | A | B | 1
A | B | C | 1
A | C | D | 1
A | C | G | 1
A | G | H | 1
E | E | F | 2
E | E | I | 2
J | J | K | 3
J | K | L | 3
(9 rows)
В SQL это нужно будет рекурсивный КТР. Какой SQL вы собираетесь использовать? – wildplasser
Я предпочитаю Oracle 10. (11g имеет некоторые дополнительные расширения относительно CTE, поэтому может быть проще) – ipj