Рекурсия в Oracle

У меня есть следующая таблица в оракуле:

Parent(arg1, arg2)

и я хочу транзитивное замыкание отношения parent. То есть, я хочу следующую таблицу

Ancestor(arg1, arg2)

Как это возможно в Oracle?

Я делаю следующее:

WITH Ancestor(arg1, arg2) AS (
 SELECT p.arg1, p.arg2 from parent p
 UNION
 SELECT p.arg1 , a.arg2 from parent p, Ancestor a 
 WHERE p.arg2 = a.arg1
)
SELECT DISTINCT * FROM Ancestor;

Я получаю сообщение об ошибке

*Cause: column aliasing in WITH clause is not supported yet
*Action: specify aliasing in defintion subquery and retry
Error at Line: 1 Column: 20

Как я могу решить эту проблему без псевдонимов столбцов?

2 ответа

WITH Ancestor(arg1, arg2) AS
 (
 SELECT p.arg1, p.arg2
 FROM parent p
 WHERE arg2 NOT IN
 (
 SELECT arg1
 FROM parent
 )
 UNION ALL
 SELECT p.arg1, a.arg2
 FROM Ancestor a 
 JOIN parent p
 ON p.arg2 = a.arg1
 )
SELECT *
FROM Ancestor

Oracle поддерживает только рекурсивный CTE с 11g Release 2.

В более ранних версиях используйте предложение CONNECT BY:

SELECT arg1, CONNECT_BY_ROOT arg2
FROM parent
START WITH
 arg2 NOT IN
 (
 SELECT arg1
 FROM parent
 )
CONNECT BY
 arg2 = PRIOR arg1


Oracle позволяет рекурсивные запросы. См.: http://www.adp-gmbh.ch/ora/sql/connect_by.html

Конечно, они обычно предполагают, что иерархические данные все в одной таблице. Разделение его на отдельные таблицы усложняет работу.

licensed under cc by-sa 3.0 with attribution.