Если у вас отношения родитель/ребенок:
CREATE TABLE t ( parent, child ) AS
SELECT 'a', 'b' FROM dual UNION ALL
SELECT 'b', 'c' FROM dual UNION ALL
SELECT 'c', 'd' FROM dual UNION ALL
SELECT 'd', 'e' FROM dual;
И вы хотите получить генеалогическое древо, начиная с b
, и получить всех потомков, тогда вы можете:
SELECT level,
t.*
FROM t
START WITH parent = 'b'
CONNECT BY PRIOR child = parent
Что выводит:
LEVEL | PARENT | CHILD
----: | :----- | :----
1 | b | c
2 | c | d
3 | d | e
Уровень 1 начинается с b
, затем уровень 2 имеет дочерний элемент b
c
, затем уровень 3 имеет дочерний элемент (внук) d
ребенка b
, и все они связаны отношением, согласно которому PRIOR
child
является (текущим) parent
.
Дополнительные примеры того, как получить различные отношения, можно найти в этом ответе.
Кроме того, ваш пример в вопросе немного сбивает с толку, поскольку он находит все пути на глубину 3 рекурсии. Если вы покажете пути, которые он прошел через данные, используя SYS_CONNECT_BY_PATH
, тогда вы получите лучшее представление:
SELECT level,
t.*,
SYS_CONNECT_BY_PATH( '('||col1||','||col2||')', '->' ) AS path
FROM (
SELECT 'a' AS col1, 'b' AS col2 FROM dual UNION ALL
SELECT 'c', 'd' FROM dual
) t
CONNECT BY level <= 3
Что выводит:
LEVEL | COL1 | COL2 | PATH
----: | :--- | :--- | :--------------------
1 | a | b | ->(a,b)
2 | a | b | ->(a,b)->(a,b)
3 | a | b | ->(a,b)->(a,b)->(a,b)
3 | c | d | ->(a,b)->(a,b)->(c,d)
2 | c | d | ->(a,b)->(c,d)
3 | a | b | ->(a,b)->(c,d)->(a,b)
3 | c | d | ->(a,b)->(c,d)->(c,d)
1 | c | d | ->(c,d)
2 | a | b | ->(c,d)->(a,b)
3 | a | b | ->(c,d)->(a,b)->(a,b)
3 | c | d | ->(c,d)->(a,b)->(c,d)
2 | c | d | ->(c,d)->(c,d)
3 | a | b | ->(c,d)->(c,d)->(a,b)
3 | c | d | ->(c,d)->(c,d)->(c,d)
Вы получаете 14 строк, потому что вы получаете 2 строки на уровне 1 (по одной для каждой комбинации входных строк), а затем 4 строки на уровне 2 (по одной для каждой входной строки для каждой строки уровня 1), а затем 8 строк на уровне 2 (по одной для каждой строки ввода). каждая входная строка для каждой строки уровня 2), и ваши выходные данные растут в геометрической прогрессии.
db‹›fiddle здесь
person
MT0
schedule
20.03.2021
(a, b)
не имеет отношения родитель/потомок к строке(b, c)
. Будет проще продемонстрировать работу с иерархиями с иерархическими данными, чем просто использоватьconnect by
(не обязательноconnect by level
- лично я предпочитаюconnect by rownum
) в качестве хака генерации строк. - person William Robertson   schedule 20.03.2021connect by
, за которым следует выражение, которое вычисляется для каждой итерации. (В документации указано, что ключевое словоprior
является обязательным, хотя это не применяется, поэтому это иногда рассматривается как хак.)rownum <= 3
верно для первых трех строк, поэтому вы получите 3 строки обратно.level <= 3
верно для первых трех уровней, что зависит от набора, с которого вы начинаете. Поскольку вы начинаете с более чем одной строки и просите ее сгенерировать все иерархии для каждой строки, вы получите обратно экспоненциальное количество строк. - person William Robertson   schedule 20.03.2021a
и еще одну дляb
. Обычно, когда мы используемconnect by
без условияprior
илиstart with
, мы используем его для генерации нескольких строк из 1 строки в двойном режиме, и нет никакого смысла основывать его на многострочном наборе, поскольку вы получаете эту бессмысленную экспоненциальную результат. Действительно,start with
иprior
и есть вся сутьconnect by
, и использовать его без них в качестве генератора строк — хак, хоть и удобный. - person William Robertson   schedule 21.03.2021