PL / SQL цикл «назад» через записи - PullRequest
0 голосов
/ 31 марта 2020

У меня есть проблема, я надеюсь, что вы можете помочь решить.

У меня есть таблица с именем PRODUCT:

Product_ID               NOT NULL NUMBER(10)       
TARGET_PRODUCT                    VARCHAR2(10)  
SOURCE_PRODUCT                    VARCHAR2(10)  

Таким образом, каждый target_product сделан из source_product (кроме первого - первый просто имеет target_product, а source_product имеет значение null) Мне нужно найти первый источник source_product для заданного target_product. Мне нужно go «вернуться» в al oop, пока исходный продукт не станет нулевым. Есть ли решение для этого сценария?

Заранее спасибо

Ответы [ 2 ]

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

Вы можете попробовать это, он вернет базовый target_product для данного target_product:

select * from (
  select PRODUCT_ID, TARGET_PRODUCT, SOURCE_PRODUCT 
  from PRODUCT
  start with target_product = '<your target product>'
  connect by prior SOURCE_PRODUCT = TARGET_PRODUCT
)
where SOURCE_PRODUCT is null;
1 голос
/ 31 марта 2020

Вам нужен не l oop, а иерархический запрос . Взгляните на следующий пример, основанный на таблице EMP Скотта.

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

SQL> select level,
  2         lpad(' ', level * 2, ' ') || e.ename name
  3  from emp e
  4  start with e.mgr is null
  5  connect by prior e.empno= e.mgr;

     LEVEL NAME
---------- ---------------
         1   KING
         2     JONES
         3       SCOTT
         4         ADAMS
         3       FORD
         4         SMITH
         2     BLAKE
         3       ALLEN
         3       WARD
         3       MARTIN
         3       TURNER
         3       JAMES
         2     CLARK
         3       MILLER

14 rows selected.

SQL>

Если вы хотите начать с середины таблицы (например, начиная с SMITH), вы "перевернуть" его:

SQL> select level lvl,
  2            lpad(' ', level * 2, ' ') || e.ename name
  3     from emp e
  4     start with e.ename = 'SMITH'
  5     connect by prior e.mgr= e.empno;

       LVL NAME
---------- ---------------
         1   SMITH
         2     FORD
         3       JONES
         4         KING

SQL>

Наконец, используя этот запрос в качестве CTE (или подзапроса, если ваша версия Forms не поддерживает CTE), выберите тот, чье имя имеет самый высокий уровень:

SQL> with temp as
  2    (select level lvl,
  3            lpad(' ', level * 2, ' ') || e.ename name
  4     from emp e
  5     start with e.ename = 'SMITH'
  6     connect by prior e.mgr= e.empno
  7    )
  8  select trim(t.name) name
  9  from temp t
 10  where t.lvl = (select max(t1.lvl) from temp t1);

NAME
---------------
KING

SQL>

Или, еще лучше, используя connect_by_isleaf:

SQL> select e.ename name
  2  from emp e
  3  where connect_by_isleaf = 1
  4  start with e.ename = 'SMITH'
  5  connect by prior e.mgr= e.empno;

NAME
---------------
KING

SQL>
...