Как Oracle оценивает иерархический запрос с "connect by rownum <= n" - PullRequest
2 голосов
/ 23 марта 2020
With A as (

   SELECT 'A' ID FROM DUAL

   UNION ALL 

   SELECT 'B' FROM DUAL

   UNION ALL

   SELECT 'C' FROM DUAL
  )

  SELECT ID 
       , LEVEL AS LVL 
       , ROWNUM 
       , SYS_CONNECT_BY_PATH(LEVEL,'->') AS LV_PATH
       , SYS_CONNECT_BY_PATH(ID,'->') AS ID_PATH
    FROM A
  CONNECT BY ROWNUM <= 3
Result
  ID      LVL   ROWNUM     LV_PATH     ID_PATH
   A       1      1         ->1          ->A
   A       2      2         ->1->2       ->A->A
   A       3      3         ->1->2->3    ->A->A->A
   B       1      4         ->1          ->B
   C       1      5         ->1          ->B

[why B and C has 1 level !?]

в результате этого запроса, B и C имеет только 1 значение (уровень?), Но A имеет 3 значения и уровень (и результат ID_PATH состоит только из A)

я понимаю использование соединения по уровням - это создание иерархической структуры, поэтому я знаю, что столбец будет n + n ^ n

, но я не знаю, почему при соединении по rownum отображаются только эти значения ...

, пожалуйста, помогите мне ТТ

1 Ответ

1 голос
/ 23 марта 2020

Ваш иерархический запрос соединяет одну строку в иерархии с другой строкой согласно критерию rownum <= 3.

Во-первых, важно понимать, что rownum - это псевдостолбец, который генерируется , когда и только если запрос решит, что будет сгенерирована строка; он всегда начинается с 1 для первой отправленной записи и увеличивается только при каждой последующей записи (поэтому вы никогда не получите результаты, когда выполняется что-то вроде where rownum > 1).

Во-вторых, важно понимать, что в Oracle иерархический запрос строится с использованием поиска в глубину.

Ваш начальный набор строк:

1. 'A'
2. 'B'
3. 'C'

Первая строка, сгенерированная запросом:

1. 'A' rownum=1 level=1

Теперь запрос возвращается назад и проверяет исходный набор строк для любых непосредственных «потомков» этой строки. Находит первую запись 'A'. Условие, чтобы определить, является ли эта строка дочерней по отношению к нашей первой строке, rownum <= 3. Поскольку rownum для генерируемой строки равно 2, условие выполняется; поэтому эта строка выдается:

2. 'A' -> 'A' rownum=2 level=2

Теперь запрос проверяет набор строк снова на наличие непосредственных «потомков» этой строки. Находит первую запись 'A'. Условие rownum <= 3 снова проверяется; поскольку rownum теперь будет 3, условие выполнено; так что эта строка выдается:

3. 'A' -> 'A' -> 'A' rownum=3 level=3

Теперь запрос проверяет набор строк снова на наличие непосредственных «потомков» этой новой строки. Тем не менее, rownum будет 4 для новой строки, поэтому он не сможет найти никаких «потомков».

Поэтому он возвращается к строке 2, сгенерированной ранее, и продолжает поиск набора строк для любых других потомков. ; опять же, rownum будет 4, поэтому он все равно не сможет найти больше детей. Он делает то же самое для строки 1 и не может найти других дочерних элементов.

Наконец, он вернулся к root дерева и перемещается к следующей записи в наборе строк:

4. 'B' rownum=4 level=1

Он делает то же самое, выполняя поиск набора строк для любых дочерних элементов этой записи, и терпит неудачу из-за условия.

Наконец, он достигает последней записи в наборе строк:

5. 'C' rownum=5 level=1

Также не удается найти дочерних элементов этой записи, и запрос завершен.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...