powered by simpleCommunicator - 2.0.51     © 2025 Programmizd 02
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Рекурсия и cycle
15 сообщений из 15, страница 1 из 1
Рекурсия и cycle
    #40039114
AXEL_111
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Доброго времени суток.
Вопрос по рекурсии, когда нужно отобразить определенные ветки дерева (где есть петля).

Нужно отобразить связь между объектами (полную ветку с петлей), когда есть имя объекта и количество уровней.

Есть входные данные:

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
with t (otpravitel, poluchatel, tovar) as (

select 'Склад_1', 'Магазин 4', 'Товар 5' from dual union 
select 'Склад_1', 'Магазин 7', 'Товар 3' from dual union 
select 'Склад_7', 'Магазин 6', 'Товар 8' from dual union 
select 'Склад_3', 'Магазин 5', 'Товар 9' from dual union 
select 'Склад_2', 'Магазин 5', 'Товар 9' from dual union 
select 'Магазин 7', 'Склад_7', 'Товар 7' from dual union 
select 'Магазин 5', 'Склад_3', 'Товар 4' from dual union 
select 'Магазин 4', 'Склад_2', 'Товар 6' from dual union 
select 'Склад_4', 'Склад_9', 'Товар 6' from dual union 
select 'Склад_9', 'Склад_2', 'Товар 2' from dual union 
select 'Склад_10', 'Магазин 6', 'Товар 5' from dual union 
select 'Склад_4', 'Склад_8', 'Товар 8' from dual union 
select 'Магазин 4', 'Магазин 9', 'Товар 9' from dual union 
select 'Магазин 9', 'Магазин 5', 'Товар 5' from dual union 
select 'Магазин 1', 'Магазин 4', 'Товар 5' from dual union 
select 'Магазин 5', 'Склад_10', 'Товар 6' from dual union 
select 'Магазин 4', 'Склад_1', 'Товар 5' from dual
)

select *
        from
(select level lvl, aa.otpravitel, aa.poluchatel,
        (connect_by_root aa.otpravitel)||sys_connect_by_path(aa.poluchatel, ' --> ') path

        from
(SELECT a.otpravitel, a.poluchatel
        FROM t a
group by a.otpravitel, a.poluchatel
) aa
connect by prior poluchatel=otpravitel  and level <= 5
start with otpravitel = 'Склад_4'
) aa
;



Результат:
LVL OTPRAVITEL POLUCHATEL PATH1 Склад_4 Склад_8 Склад_4 --> Склад_81 Склад_4 Склад_9 Склад_4 --> Склад_92 Склад_9 Склад_2 Склад_4 --> Склад_9 --> Склад_23 Склад_2 Магазин 5 Склад_4 --> Склад_9 --> Склад_2 --> Магазин 54 Магазин 5 Склад_10 Склад_4 --> Склад_9 --> Склад_2 --> Магазин 5 --> Склад_105 Склад_10 Магазин 6 Склад_4 --> Склад_9 --> Склад_2 --> Магазин 5 --> Склад_10 --> Магазин 64 Магазин 5 Склад_3 Склад_4 --> Склад_9 --> Склад_2 --> Магазин 5 --> Склад_35 Склад_3 Магазин 5 Склад_4 --> Склад_9 --> Склад_2 --> Магазин 5 --> Склад_3 --> Магазин 5

А ожидаемый результат:
LVL OTPRAVITEL POLUCHATEL PATH1 Склад_4 Склад_9 Склад_4 --> Склад_92 Склад_9 Склад_2 Склад_4 --> Склад_9 --> Склад_23 Склад_2 Магазин 5 Склад_4 --> Склад_9 --> Склад_2 --> Магазин 54 Магазин 5 Склад_3 Склад_4 --> Склад_9 --> Склад_2 --> Магазин 5 --> Склад_35 Склад_3 Магазин 5 Склад_4 --> Склад_9 --> Склад_2 --> Магазин 5 --> Склад_3 --> Магазин 5

Заранее благодарю.
...
Рейтинг: 0 / 0
Рекурсия и cycle
    #40039235
Фотография Stax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AXEL_111,

CONNECT_BY_ISCYCLE, nocycle

ps
как-то странно вы ищете цикл, напр если цикл на третьем левеле

....
stax
...
Рейтинг: 0 / 0
Рекурсия и cycle
    #40039274
Lary Denis
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Stax, что за подсказки?? Где готовое решение?
...
Рейтинг: 0 / 0
Рекурсия и cycle
    #40039280
Фотография Stax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Lary Denis
Stax, что за подсказки?? Где готовое решение?

готового нет, дипресняк

не знаю требований, мож там дерево на млн строк

макет, решение влоб
на практике возможно делать так нельзя
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
with t (otpravitel, poluchatel, tovar) as (
select 'Склад_1', 'Магазин 4', 'Товар 5' from dual union
select 'Склад_1', 'Магазин 7', 'Товар 3' from dual union
select 'Склад_7', 'Магазин 6', 'Товар 8' from dual union
select 'Склад_3', 'Магазин 5', 'Товар 9' from dual union
select 'Склад_2', 'Магазин 5', 'Товар 9' from dual union
select 'Магазин 7', 'Склад_7', 'Товар 7' from dual union
select 'Магазин 5', 'Склад_3', 'Товар 4' from dual union
select 'Магазин 4', 'Склад_2', 'Товар 6' from dual union
select 'Склад_4', 'Склад_9', 'Товар 6' from dual union
select 'Склад_9', 'Склад_2', 'Товар 2' from dual union
select 'Склад_10', 'Магазин 6', 'Товар 5' from dual union
select 'Склад_4', 'Склад_8', 'Товар 8' from dual union
select 'Магазин 4', 'Магазин 9', 'Товар 9' from dual union
select 'Магазин 9', 'Магазин 5', 'Товар 5' from dual union
select 'Магазин 1', 'Магазин 4', 'Товар 5' from dual union
select 'Магазин 5', 'Склад_10', 'Товар 6' from dual union
select 'Магазин 4', 'Склад_1', 'Товар 5' from dual
)
, aa as (
SELECT a.otpravitel, a.poluchatel
        FROM t a
group by a.otpravitel, a.poluchatel)
select level lvl, aa.otpravitel, aa.poluchatel,
        (connect_by_root aa.otpravitel)||sys_connect_by_path(aa.poluchatel, '>') path
,CONNECT_BY_ISCYCLE  iscycle
,level
        from aa
connect by NOCYCLE prior poluchatel=otpravitel  --and level <= 5
       and 1= (
        select max(CONNECT_BY_ISCYCLE)
        from aa bb
        connect by NOCYCLE prior bb.poluchatel=bb.otpravitel  --and level <= 5
        start with bb.otpravitel = aa.poluchatel
        )
start with otpravitel = 'Склад_4'
       and 1= (
        select max(CONNECT_BY_ISCYCLE)
        from aa bb
        connect by NOCYCLE prior bb.poluchatel=bb.otpravitel  --and level <= 5
        start with bb.otpravitel = aa.poluchatel
        )
SQL> /

       LVL OTPRAVITE POLUCHATE PATH                                                            ISCYCLE      LEVEL
---------- --------- --------- ------------------------------------------------------------ ---------- ----------
         1 Склад_4   Склад_9   Склад_4>Склад_9                                                       0          1
         2 Склад_9   Склад_2   Склад_4>Склад_9>Склад_2                                               0          2
         3 Склад_2   Магазин 5 Склад_4>Склад_9>Склад_2>Магазин 5                                     0          3
         4 Магазин 5 Склад_3   Склад_4>Склад_9>Склад_2>Магазин 5>Склад_3                             1          4



.....
stax
...
Рейтинг: 0 / 0
Рекурсия и cycle
    #40039283
Фотография env
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AXEL_111,

Без даты движения или иного нарастающего показателя интерпретировать ваши данные можно как угодно.
...
Рейтинг: 0 / 0
Рекурсия и cycle
    #40039287
Фотография Stax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
env,

ето просто пример дерева
не обязательно поставки, можно и на начальник/подчиненный

.....
stax
...
Рейтинг: 0 / 0
Рекурсия и cycle
    #40039306
AXEL_111
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
env
AXEL_111,

Без даты движения или иного нарастающего показателя интерпретировать ваши данные можно как угодно.


Цикл может быть и в первом звене и в третьем (в этом и вся загвоздка).
По исходному значению запрос строится за определенный период. Нужно видеть связь объектов (прямую или через звено/звенья).
...
Рейтинг: 0 / 0
Рекурсия и cycle
    #40039309
AXEL_111
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Stax
Lary Denis
Stax, что за подсказки?? Где готовое решение?

готового нет, дипресняк

не знаю требований, мож там дерево на млн строк

макет, решение влоб
на практике возможно делать так нельзя
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
with t (otpravitel, poluchatel, tovar) as (
select 'Склад_1', 'Магазин 4', 'Товар 5' from dual union
select 'Склад_1', 'Магазин 7', 'Товар 3' from dual union
select 'Склад_7', 'Магазин 6', 'Товар 8' from dual union
select 'Склад_3', 'Магазин 5', 'Товар 9' from dual union
select 'Склад_2', 'Магазин 5', 'Товар 9' from dual union
select 'Магазин 7', 'Склад_7', 'Товар 7' from dual union
select 'Магазин 5', 'Склад_3', 'Товар 4' from dual union
select 'Магазин 4', 'Склад_2', 'Товар 6' from dual union
select 'Склад_4', 'Склад_9', 'Товар 6' from dual union
select 'Склад_9', 'Склад_2', 'Товар 2' from dual union
select 'Склад_10', 'Магазин 6', 'Товар 5' from dual union
select 'Склад_4', 'Склад_8', 'Товар 8' from dual union
select 'Магазин 4', 'Магазин 9', 'Товар 9' from dual union
select 'Магазин 9', 'Магазин 5', 'Товар 5' from dual union
select 'Магазин 1', 'Магазин 4', 'Товар 5' from dual union
select 'Магазин 5', 'Склад_10', 'Товар 6' from dual union
select 'Магазин 4', 'Склад_1', 'Товар 5' from dual
)
, aa as (
SELECT a.otpravitel, a.poluchatel
        FROM t a
group by a.otpravitel, a.poluchatel)
select level lvl, aa.otpravitel, aa.poluchatel,
        (connect_by_root aa.otpravitel)||sys_connect_by_path(aa.poluchatel, '>') path
,CONNECT_BY_ISCYCLE  iscycle
,level
        from aa
connect by NOCYCLE prior poluchatel=otpravitel  --and level <= 5
       and 1= (
        select max(CONNECT_BY_ISCYCLE)
        from aa bb
        connect by NOCYCLE prior bb.poluchatel=bb.otpravitel  --and level <= 5
        start with bb.otpravitel = aa.poluchatel
        )
start with otpravitel = 'Склад_4'
       and 1= (
        select max(CONNECT_BY_ISCYCLE)
        from aa bb
        connect by NOCYCLE prior bb.poluchatel=bb.otpravitel  --and level <= 5
        start with bb.otpravitel = aa.poluchatel
        )
SQL> /

       LVL OTPRAVITE POLUCHATE PATH                                                            ISCYCLE      LEVEL
---------- --------- --------- ------------------------------------------------------------ ---------- ----------
         1 Склад_4   Склад_9   Склад_4>Склад_9                                                       0          1
         2 Склад_9   Склад_2   Склад_4>Склад_9>Склад_2                                               0          2
         3 Склад_2   Магазин 5 Склад_4>Склад_9>Склад_2>Магазин 5                                     0          3
         4 Магазин 5 Склад_3   Склад_4>Склад_9>Склад_2>Магазин 5>Склад_3                             1          4



.....
stax


Спасибо за помощь.

Сейчас буду пробовать отработать.
...
Рейтинг: 0 / 0
Рекурсия и cycle
    #40039313
Фотография Stax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AXEL_111

в первом звене


ето
poluchatel = otpravitel = 'Склад_4'

....
stax
...
Рейтинг: 0 / 0
Рекурсия и cycle
    #40039322
AXEL_111
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Stax
AXEL_111

в первом звене


ето
poluchatel = otpravitel = 'Склад_4'

....
stax


Прошу прощение, ОШИБСЯ. Второе звено, когда обратно на 'Склад_4'
...
Рейтинг: 0 / 0
Рекурсия и cycle
    #40039333
Фотография Stax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AXEL_111
Сейчас буду пробовать отработать.


мож Вам для анализа будет просто достаточно sys_connect_by_path
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
0  , aa as (
 21  SELECT a.otpravitel, a.poluchatel
 22          FROM t a
 23  group by a.otpravitel, a.poluchatel)
 24  --
 25  select * from (
 26   select level lvl, aa.otpravitel, aa.poluchatel,connect_by_root aa.otpravitel||sys_connect_by_path(aa.poluchatel, '>') path
 27             ,CONNECT_BY_ISCYCLE  iscycle
 28   from aa
 29   connect by NOCYCLE prior poluchatel=otpravitel  --and level <= 5
 30   start with otpravitel = 'Склад_4'
 31* ) where iscycle=1
SQL> /

       LVL OTPRAVITE POLUCHATE PATH                                                            ISCYCLE
---------- --------- --------- ------------------------------------------------------------ ----------
         4 Магазин 5 Склад_3   Склад_4>Склад_9>Склад_2>Магазин 5>Склад_3                             1



зы
можно искать "листовой" узел с ISCYCLE и от него ити обратно к корню

.....
stax
...
Рейтинг: 0 / 0
Рекурсия и cycle
    #40039362
Фотография env
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AXEL_111,

Из чего следует, какое звено в цикле первое?
...
Рейтинг: 0 / 0
Рекурсия и cycle
    #40039417
AXEL_111
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
env
AXEL_111,

Из чего следует, какое звено в цикле первое?


Например ветка: Склад_4>Склад_9>Склад_2>Магазин 5>Склад_3>Магазин 5

1зв. Склад_4>Склад_9;
2зв. Склад_9>Склад_2;
3зв. Склад_2>Магазин 5;
4зв. Магазин 5>Склад_3;
5зв. Склад_3>Магазин 5.
...
Рейтинг: 0 / 0
Рекурсия и cycle
    #40039434
Фотография env
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AXEL_111,

Как имея на руках только данные понять, что ветка начинается со Склад4? Без дополнительного внешнего контекста.
...
Рейтинг: 0 / 0
Рекурсия и cycle
    #40039440
AXEL_111
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
env
AXEL_111,

Как имея на руках только данные понять, что ветка начинается со Склад4? Без дополнительного внешнего контекста.


Начало ветки (Отправитель) указывается как константа.
...
Рейтинг: 0 / 0
15 сообщений из 15, страница 1 из 1
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Рекурсия и cycle
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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