Иерархический запрос Oracle: как включить родительский уровень - PullRequest
2 голосов
/ 21 мая 2009

У меня есть иерархический запрос для отслеживания структуры отчетности. Это почти работает, за исключением того, что он не сообщает об узле самого верхнего уровня, вероятно потому, что люди верхнего уровня «отчитываются» перед собой.

Запрос:

select
  level,
  empid, 
  parentid
from usertable
connect by nocycle prior parentid= empid
start with empid = 50

Это производит:

LEVEL  EMPID PARENTID               
------ ----- --------  
1      50    258            
2      258   9555
3      9555  17839

Я не получаю уровень 4, так как это будет выглядеть так:

4      17839 17839

Без изменения данных, есть ли способ изменить мой запрос так, чтобы были возвращены все 4 уровня? Цель состоит в том, чтобы получить empids, поэтому я могу сделать проверку на

id in (hierarchical subquery)

Кстати, если я удаляю ноцикл из запроса, я получаю ошибку.

Ответы [ 5 ]

5 голосов
/ 21 мая 2009

Крис,

Вы получаете только 3 строки, потому что ваша строка верхнего уровня не настроена так, как она должна обрабатывать иерархические запросы. Обычно в строке верхнего уровня, или президент KING в хорошо известной таблице EMP Oracle, нет менеджера. В вашем случае вы должны установить не парентид 17389 на 17389, а NULL. Либо обновите таблицу соответствующим образом, либо воспользуйтесь представлением, чтобы приспособиться к этой ситуации.

Пример:

SQL> select empno
  2       , mgr
  3    from emp
  4   where empno in (7876,7788,7566,7839)
  5  /

     EMPNO        MGR
---------- ----------
      7566       7839
      7788       7566
      7839       7839
      7876       7788

4 rijen zijn geselecteerd.

Эта часть таблицы EMP имеет четыре уровня с ее строкой верхнего уровня (7839), установленной на себя. То же, что ваш empid 17839. И это приводит только к трем строкам, использующим ваш запрос:

SQL>  select level
  2        , empno
  3        , mgr
  4     from emp
  5  connect by nocycle prior mgr = empno
  6    start with empno = 7876
  7  /

     LEVEL      EMPNO        MGR
---------- ---------- ----------
         1       7876       7788
         2       7788       7566
         3       7566       7839

3 rijen zijn geselecteerd.

Либо используйте (встроенное) представление, чтобы установить для столбца mgr / parentid значение null для верхнего уровня:

SQL>  select level
  2        , empno
  3        , mgr
  4     from ( select empno
  5                 , nullif(mgr,empno) mgr
  6              from emp
  7          )
  8  connect by nocycle prior mgr = empno
  9    start with empno = 7876
 10  /

     LEVEL      EMPNO        MGR
---------- ---------- ----------
         1       7876       7788
         2       7788       7566
         3       7566       7839
         4       7839

4 rijen zijn geselecteerd.

Или исправьте ваши данные с помощью оператора UPDATE:

SQL> update emp
  2     set mgr = null
  3   where empno = 7839
  4  /

1 rij is bijgewerkt.

SQL>  select level
  2        , empno
  3        , mgr
  4     from emp
  5  connect by nocycle prior mgr = empno
  6    start with empno = 7876
  7  /

     LEVEL      EMPNO        MGR
---------- ---------- ----------
         1       7876       7788
         2       7788       7566
         3       7566       7839
         4       7839

4 rijen zijn geselecteerd.

И после исправления вы также можете опустить ключевое слово NOCYCLE.

С уважением, Роб.

3 голосов
/ 21 мая 2009

Вы должны сделать иерархию наоборот, от корня до листьев.

select
  level,
  empid, 
  parentid
from usertable
start with empid = 17839
connect by empid != 17839 and prior empid = parentid

LEVEL                  EMPID                  PARENTID               
---------------------- ---------------------- ---------------------- 
1                      17839                  17839                  
2                      9555                   17839                  
3                      258                    9555                   
4                      50                     258                    

4 rows selected
1 голос
/ 10 декабря 2010

Вам не нужно менять свою структуру.

просто используйте следующий запрос

select
  level,
  empid,
  parentid
from usertable
connect by prior parentid = empid
       AND parentid <> empid  -- This line prohibits cycling and ALLOWS a row where parentid = empid
start with empid = 50
0 голосов
/ 06 января 2016

Ответ Ван Хеддегема Роланда у меня не работает, я уже пробовал это, но мне удалось сделать это без встроенного представления в предложении подключения, добавив: -

and prior empid <> parentid

Следующий пост объясняет, почему это работает - если вы можете обдумать это! Хотя это действительно звучит логично, если вы понимаете это. (Это связано с порядком вычисления каждой стороны оператора <>.)

Oracle: подключение по циклу в пользовательских данных

Встроенное представление будет работать, но без исследования вашего конкретного набора данных я не знаю, какое влияние может оказать встроенное представление на путь запроса. Добавление дополнительного предложения, вероятно, является «правильным» способом сделать это в большинстве ситуаций, ИМХО.

0 голосов
/ 21 мая 2009

кажется, что у вас есть цикл данных. Без «ноцикла» это не сработает сразу. Если вы знаете, что все ваши данные имеют максимальный уровень вложенности 4, вы можете добавить условие «и уровень <= 4» и удалить ноцикл. Должно работать. </p>

...