подключение по предварительному запросу: использование PRIOR для перехода на 2 уровня вверх - PullRequest
0 голосов
/ 04 августа 2020

У меня есть следующее предварительное подключение SQL, которое по существу начинается с листового узла и продвигается вверх по дереву до родительского «tree-trun c» (уровень-1):

with my_tree as (
   select 'level 4.1' node, 'level 3.1' parent_node from dual union
   select 'level 4.2' node, 'level 3.2' parent_node from dual union
   select 'level 3.1' node, 'level 2'   parent_node from dual union
   select 'level 3.2' node, 'level 2'   parent_node from dual union
   select 'level 2'   node, 'level 1'   parent_node from dual union
   select 'level 1'   node, ''          parent_node from dual
)
select level, t.node, t.parent_node, prior t.node child_that_pointed_me_here
from   my_tree t
connect by t.node = prior t.parent_node
start with t.node like 'level 4%'

Это дает мне следующий результат:

level node      parent_node child_who_pointed_me_here
----- --------- ----------- -------------------------
1     level 4.1 level 3.1 
2     level 3.1 level 2     level 4.1
3     level 2   level 1     level 3.1
4     level 1               level 2
1     level 4.2 level 3.2 
2     level 3.2 level 2     level 4.2
3     level 2   level 1     level 3.2
4     level 1               level 2

Вы можете видеть, что инструкция prior t.node (обозначенная как столбец child_who_pointed_me_here) приводит меня к данным в «предыдущей» записи ( то есть дочерний узел, с которого я начал), что именно то, что я хочу. Другими словами, ключевое слово PRIOR дает мне доступ к данным в «предыдущей» записи.

Но я бы хотел получить доступ к данным на 2 уровня (или 3 или 4 уровня) ранее. Что-то вроде prior prior t.node. Желаемый результат будет выглядеть следующим образом:

level node      parent_node child_who_pointed_me_here grandchild_who_pointed_me_here
----- --------- ----------- ------------------------- ------------------------------
1     level 4.1 level 3.1 
2     level 3.1 level 2     level 4.1
3     level 2   level 1     level 3.1                 level 4.1
4     level 1               level 2                   level 3.1
1     level 4.2 level 3.2
2     level 3.2 level 2     level 4.2
3     level 2   level 1     level 3.2                 level 4.2
4     level 1               level 2                   level 3.2

Я пробовал очевидный prior prior t.node, но он, очевидно, просто приводит к ошибке типа неподдерживаемого синтаксиса.

поэтому вопрос: Есть ли в connect-by SQL конструкция, которая позволила бы мне go 2 уровня назад (или вверх) по пути?

Я использую Oracle 12 c для построения этого SQL, но ответы в любом вкусе SQL приветствуются.

1 Ответ

1 голос
/ 04 августа 2020

sys_connect_by_path предоставит вам всю родословную, откуда вы достигли текущей строки.

Я выполняю манипуляции со строкой в ​​sys_connect_by_path, изменяя и выбирая позиции индекса второго '/' и третьего '/ 'для извлечения данных между

Используя эту строку, мы можем использовать следующее для извлечения двух слоев следующим образом:

with my_tree as (
   select 'level 4.1' node, 'level 3.1' parent_node from dual union
   select 'level 4.2' node, 'level 3.2' parent_node from dual union
   select 'level 3.1' node, 'level 2'   parent_node from dual union
   select 'level 3.2' node, 'level 2'   parent_node from dual union
   select 'level 2'   node, 'level 1'   parent_node from dual union
   select 'level 1'   node, ''          parent_node from dual
)
select level, t.node, t.parent_node, prior t.node child_that_pointed_me_here
       ,sys_connect_by_path(t.node,'/') as lineage
       ,rtrim(
        reverse(
         substr(
               reverse(sys_connect_by_path(t.node,'/'))
               ,instr(reverse(sys_connect_by_path(t.node,'/')),'/',1,2)
               ,instr(reverse(sys_connect_by_path(t.node,'/')),'/',1,3)
               -
               instr(reverse(sys_connect_by_path(t.node,'/')),'/',1,2)
               )
              )
        ,'/') as two_level_up
  from my_tree t
connect by t.node = prior t.parent_node
start with t.node like 'level 4%'



+-------+-----------+-------------+----------------------------+--------------------------------------+--------------+
| LEVEL |   NODE    | PARENT_NODE | CHILD_THAT_POINTED_ME_HERE |               LINEAGE                | TWO_LEVEL_UP |
+-------+-----------+-------------+----------------------------+--------------------------------------+--------------+
|     1 | level 4.1 | level 3.1   | null                       | /level 4.1                           |              |
|     2 | level 3.1 | level 2     | level 4.1                  | /level 4.1/level 3.1                 |              |
|     3 | level 2   | level 1     | level 3.1                  | /level 4.1/level 3.1/level 2         | level 4.1    |
|     4 | level 1   |             | level 2                    | /level 4.1/level 3.1/level 2/level 1 | level 3.1    |
|     1 | level 4.2 | level 3.2   |                            | /level 4.2                           |              |
|     2 | level 3.2 | level 2     | level 4.2                  | /level 4.2/level 3.2                 |              |
|     3 | level 2   | level 1     | level 3.2                  | /level 4.2/level 3.2/level 2         | level 4.2    |
|     4 | level 1   |             | level 2                    | /level 4.2/level 3.2/level 2/level 1 | level 3.2    |
+-------+-----------+-------------+----------------------------+--------------------------------------+--------------+

dbfiddle https://dbfiddle.uk/?rdbms=oracle_11.2&fiddle=0448131cc387e52eab3126dfce0a7cde

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