WITH RECURSIVE linked(id, path) AS (
SELECT :id,
ARRAY[:id]
UNION ALL
SELECT t3b.table1_id,
path || t3b.table1_id
FROM table3 AS t3a, table3 AS t3b, linked AS l
WHERE t3a.table1_id = l.id
AND t3b.table2_id = t3a.table2_id
AND t3b.table1_id != t3a.table1_id
AND NOT (t3b.table1_id = ANY(path))
)
SELECT * FROM linked;
1. Создаём списки уже найденных кабелей, муфт и кроссов.
2. Создаём списки муфт и кроссов, которые надо найти. Добавляем исходный кросс.
3. Пока поисковые списки не пусты
- 3a. Берём следующие муфту или кросс из начала поисковых списков.
- 3b. Добавляем их в список найденных.
- 3с. Ищем в базе все кабеля, один из концов которых соединён с текущей муфтой или кроссом, и кабель ещё не входит в список найденных. Получаем список кабелей и id муфты или кросса на втором конце.
- 3d. Добавляем кабеля в список найденных.
- 3e. Проверяем, если муфта или кросс есть в списках найденных или в списках поиска, то имеем не дерево, а кольцо. Если их там нет - добавляем их в конец списков поиска.
- 3f. В дерево добавляем соответствующие кабелям связи между муфтами и кроссами.