powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Вопрос по connect by
5 сообщений из 5, страница 1 из 1
Вопрос по connect by
    #39523882
SQL_boy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Ребята всем привет!

Можете пояснить алгоритм работы иерархических запросов? В частности следующий пример:
Код: plsql
1.
2.
3.
4.
5.
With Test(Name) as  
    (select 'Tom' from dual)
    
select Name, level from Test   
    connect by level<=2



Возвращает то, что я и ожидал: одна запись выводится два раза по иерархии (1*2) = 2
NameLevelTom1Tom2

Далее добавляю еще одну запись (кортеж) в таблицу и выполняю тот же запрос.
По моим ожиданиям: первым делом выполняется выборка из таблицы, далее к ней применяется условие в Connect by. Причем, так как не указан root, то родительской считается каждая запись. Т.е. для каждой записи будет возвращено две записи в соответствии с условием Connect by. Т.е я ожидаю что вернется: 1*2 + 1*2 = 4 записи. Но вернулось:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
With Test(Name) as  
    (select 'Tom' from dual
    union
    select 'Jerry' from dual)
    
select Name, level from Test   
    connect by level<=2    


NameLevelJerry1Jerry2Tom2Tom1Jerry2Tom2

Вернулось 6 записей! Можете пояснить почему ? И как шел алгоритм?
...
Рейтинг: 0 / 0
Вопрос по connect by
    #39523902
Фотография Elic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SQL_boyернулось 6 записей! Можете пояснить почему ? И как шел алгоритм?Все являются детьми всех.
...
Рейтинг: 0 / 0
Вопрос по connect by
    #39523903
Фотография andrey_anonymous
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SQL_boyВернулось 6 записей! Можете пояснить почему ? И как шел алгоритм?
Для начала следует осознать, что Вы не указали условия соединения.
По аналогии с декартовым произведением, connect by в этих условиях пытается соединять всех со всеми.
Итого: 2 записи level 1 и по два чилда level 2 у каждой. 2*(1+2)=6
...
Рейтинг: 0 / 0
Вопрос по connect by
    #39524878
SQL_boy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
andrey_anonymousSQL_boyВернулось 6 записей! Можете пояснить почему ? И как шел алгоритм?
Для начала следует осознать, что Вы не указали условия соединения.
По аналогии с декартовым произведением, connect by в этих условиях пытается соединять всех со всеми.
Итого: 2 записи level 1 и по два чилда level 2 у каждой. 2*(1+2)=6

Ребята спасибо за ответы! Вроде сначала посчитал, что понял. А начал проверять и понял, что не понял =)
Сейчас озвучу свой ход мысли и параллельно вопросы, возникшие в процессе.

Есть таблица(отношение), содержащая две записи(кортежа). Применяем к ней выборку с connect by:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
With Test(Name) as  
    (select 'Tom' from dual
    union
    select 'Jerry' from dual)
    
select Name, level from Test   
    connect by level<=2  



Итак, в соответствии с оракловой докой:
Oracle1) Oracle selects the root row(s) of the hierarchy--those rows that satisfy the START WITH condition.
2) Oracle selects the child rows of each root row. Each child row must satisfy the condition of the CONNECT BY condition with respect to one of the root rows.


Так как в запросе явно не указано, какая запись является родительской (root), то считаем все записи root-ами.
Код: plsql
1.
2.
'Tom'   --- Root
'Jerry' --- Root



Берем первую запись - 'Tom', она у нас root и, как понимаю условия соединения CONNECT BY к ней не применяется (поправьте если не так), а применяется это условие ко всем последующим записям. В нашем случае берем следующую запись Jerry и уже к ней применяем условие connect by level<=2. Вот здесь я думал, что выполняется реляционная операция - произведение(декартово): Jerry * 2 (т.к.connect by level<=2). В итоге получаем отношение из двух кортежей. Т.е у нас получается одна запись root - Tom (level=1), плюс два его потомка (две записи Jerry level 2), Итого три записи:

Name Level'Tom'1'Jerry'2'Jerry'2

Далее переходит к второй root записи - Jerry и алгоритм повторяется. Получаем также три записи:
Name Level'Jerry'1'Tom'2'Tom'2

На выходе получаем результат, который я приводил в первом посте этой темы:
Name LevelJerry 1Jerry 2Tom 2Tom 1Jerry 2Tom 2

Потом я решил переписать условие connect by, вместо 2 поставил 3:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
With Test(Name) as  
    (select 'Tom' from dual
    union
    select 'Jerry' from dual)
    
select Name, level from Test   
    connect by level<=3    



Я ожидал, что вернется 8 записей: (Tom (root) + 3 потомка (Jerry)) + (Jerry(root) + 3 потомка Tom). Но результат был такой:
Name LevelJerry 1Jerry 2Jerry 3Tom 3Tom 2Jerry 3Tom 3Tom 1Jerry 2Jerry 3Tom 3Tom 2Jerry 3Tom 3

14 записей! Что-то не так я понял, алгоритм мой был ошибочный! Что не так?
...
Рейтинг: 0 / 0
Вопрос по connect by
    #39524885
Фотография dbms_photoshop
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SQL_boy,

Еще раз, у тебя нет отношения родитель - потомок в условии соединения (оператор PRIOR),
соответсвенно когда выполняется переход на новый уровень все записи в таблице соответствуют условию соединения.
Переход на новый уровень выполняется пока не будет построено два уровня.
При переходе на новый уровень все записи таблицы являются детьми всех узлов уровня.

Когда это осознаешь - можешь переходить к анализу запроса.
Код: plsql
1.
2.
3.
4.
5.
6.
7.
With Test(Name) as  
    (select 'Tom' from dual
    union
    select 'Jerry' from dual)
    
select Name, level from Test   
    connect by rownum<=3    
...
Рейтинг: 0 / 0
5 сообщений из 5, страница 1 из 1
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Вопрос по connect by
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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