powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Обход дерева (выбрать все связи), Oracle12с
4 сообщений из 4, страница 1 из 1
Обход дерева (выбрать все связи), Oracle12с
    #39715090
Ora uSeR
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Есть схема связи документов (входящие-исходящие письма):
img

При создании новой связи документа 1 с документом 2 в таблицу пишется 2 строки:
Код: plaintext
1.
2.
3.
PARENT_ID   ID
NULL        283
283         245

При установлении связи с документом, который уже имеет историю (проверяю наличие PARENT_ID) в таблицу пишется только одна запись:
Код: plaintext
1.
2.
PARENT_ID   ID
245         264

История связей:
обернул данные в with
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
WITH t1 AS (
	SELECT 1  AS PK, NULL AS PARENT_ID, 100 AS ID FROM dual  UNION ALL --начало истории другого документа
	SELECT 2  AS PK, NULL AS PARENT_ID, 283 AS ID FROM dual  UNION ALL
	SELECT 3  AS PK, NULL AS PARENT_ID, 284 AS ID FROM dual  UNION ALL
	SELECT 4  AS PK, NULL AS PARENT_ID, 231 AS ID FROM dual  UNION ALL
	SELECT 5  AS PK, 283  AS PARENT_ID, 245 AS ID FROM dual  UNION ALL
	SELECT 6  AS PK, 284  AS PARENT_ID, 245 AS ID FROM dual  UNION ALL
	SELECT 7  AS PK, 231  AS PARENT_ID, 247 AS ID FROM dual  UNION ALL
	SELECT 8  AS PK, 100  AS PARENT_ID, 101 AS ID FROM dual  UNION ALL  --продолжение истории другого документа
	SELECT 9  AS PK, 245  AS PARENT_ID, 264 AS ID FROM dual  UNION ALL
	SELECT 10 AS PK, 245  AS PARENT_ID, 265 AS ID FROM dual  UNION ALL
	SELECT 11 AS PK, 247  AS PARENT_ID, 265 AS ID FROM dual  UNION ALL
	SELECT 12 AS PK, 247  AS PARENT_ID, 273 AS ID FROM dual  UNION ALL
	SELECT 13 AS PK, 264  AS PARENT_ID, 252 AS ID FROM dual
)
select ID
from dual;
/




Необходимо получать ВСЮ историю связей по любому из ID документа, допустим, ID = 273.
В примере есть 2 строки ( t1.PK IN (1, 8) ) которые не должны выводиться - это история другого документа.


Немного о попытках
В части решения средствами SQL набрёл на не плохую статью с парой примеров, но применить на практике так и не получилось..


1)
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
WITH
numbers ( n ) AS (
   SELECT 1 AS n
   FROM dual -- исходное множество -- одна строка
  	UNION ALL                      -- символическое «объединение» строк
   SELECT n + 1 AS n               -- рекурсия: добавок к предыдущему результату
   FROM   numbers                  -- предыдущий результат в качестве источника данных
    WHERE  n < 5                   -- если не ограничить, будет бесконечная рекурсия
)
SELECT n
FROM numbers             		   -- основной запрос
;




2)
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
WITH
  anchor1234 ( n ) AS (             -- обычный
     SELECT 1 FROM dual UNION ALL
     SELECT 2 FROM dual UNION ALL
     SELECT 3 FROM dual UNION ALL
     SELECT 4 FROM dual
  )
, numbers ( n ) AS (                -- рекурсивный
     SELECT n FROM anchor1234
        UNION ALL
     SELECT n + 1 AS n
     FROM   numbers
     WHERE n < 5
  )
SELECT n FROM numbers
;
/


...
Рейтинг: 0 / 0
Обход дерева (выбрать все связи), Oracle12с
    #39715099
merch
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ora uSeR,
Код: plsql
1.
connect by
...
Рейтинг: 0 / 0
Обход дерева (выбрать все связи), Oracle12с
    #39715111
Фотография dbms_photoshop
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ora uSeR,

Поскольку интересуют ВСЕ связанные документы безотносительно направления связи, то это задача на ненаправленном графе.
Подобные задачи на SQL нормально не решаются.
Относительно эффективно в SQL можно решать только задачи на напраленных (где проход допустим только в направлении связи) структурах, будь то дерево или граф.

connect by может вернуть все связанные но это будет крайне избыточный перебор
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
select id, min(lvl) dist
  from (select t1.*, level lvl
          from t1
        start with id = 273
        connect by nocycle (prior parent_id in (id, parent_id) or prior id in (id, parent_id)))
        unpivot (id for type in (parent_id, id))
group by id
order by 2;

        ID       DIST
---------- ----------
       247          1
       273          1
       231          2
       265          2
       245          3
       284          4
       283          4
       264          4
       252          5

9 rows selected.


Нормальный подход в таких случаях это обход графа к глубину, который использует список посещенных узлов.

Механизм rec with тоже непригоден для поддержания списка обойденных, то есть только PL/SQL.
...
Рейтинг: 0 / 0
Обход дерева (выбрать все связи), Oracle12с
    #39715189
Фотография Sayan Malakshinov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор форума
...
Рейтинг: 0 / 0
4 сообщений из 4, страница 1 из 1
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Обход дерева (выбрать все связи), Oracle12с
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]