Рекурсивный расчет SQL - Невозможно выполнить рекурсивный расчет - PullRequest
0 голосов
/ 12 апреля 2019

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

Мой набор данных выглядит следующим образом (есть дополнительные функции, которые мне не нужны):

| Root_Part_No | Sub_Part_No | Sub_Part_Quant |
|--------------|-------------|----------------|
| 132EER       | 122FYY      | 4              |
| 132EER       | 766WWW      | 2              |
| 132EER       | 001EWW      | 1              |
| 132EER       | 472WQA      | 1              |
| 132EER       | 632OIR      | 1              |
| 132EER       | 874RTG      | 1              |
| 132EER       | 888III      | 10             |
| 132EER       | 235CVV      | 5              |

Я могу рассчитать скважину первого уровня, используя следующий запрос:

SELECT 
    Root_Part_No, 
    TRIM(Sub_Part_No) AS "Part", 
    Sub_Part_Qty

FROM 
    TblBOM 

WHERE
    Root_Part_No LIKE "132EE%" 
    AND isEmptyInd != 'Yes'

ORDER BY Root_Part_No, Sub_Part_Qty;

Однако, что мне нужно для выполнения, - это возможность впоследствии рассчитать спецификацию для каждого из Sub_Part_No, возвращаемых для элемента, который я ввожу, чтобы в итоге получить таблицу, которая выглядит следующим образом:

| Root_Part_No | Sub_Part_No | Sub_Part_Quant |
|--------------|-------------|----------------|
| 132EER       | 122FYY      | 4              |
| 132EER       | 766WWW      | 2              |
| 132EER       | 001EWW      | 1              |
| 132EER       | 472WQA      | 1              |
| 132EER       | 632OIR      | 1              |
| 132EER       | 874RTG      | 1              |
| 132EER       | 888III      | 10             |
| 132EER       | 235CVV      | 5              |
| 122FYY       | 849ZXA      | 2              |
| 122FYY       | 990JUI      | 10             |
| 122FYY       | 211EEW      | 5              |
| 122FYY       | 211VVV      | 2              |
| 766WWW       | 001EWW      | 10             |
| 766WWW       | 176LKJ      | 2              |
...etc

Я попробовал следующие два ресурса:

Я запутался в разделе join во второй части UNION. Любая помощь на пути вперед приветствуется.

С RPL AS ( ВЫБЕРИТЕ Root_Part_No, TRIM (Sub_Part_No) AS "Часть", Sub_Part_Qty ОТ TblBOM
ГДЕ Root_Part_No НРАВИТСЯ "132EE%" И isEmptyInd! = 'Да'

UNION ALL

SELECT Root_Part_No, TRIM(Sub_Part_No) AS "Part", Sub_Part_Qty
FROM TblBOM
LEFT JOIN -- I am confusion

    )

  SELECT DISTINCT -- I am also confusion

1 Ответ

2 голосов
/ 12 апреля 2019

Простой рекурсивный запрос, чтобы получить то, что вы хотите:

with
i (root_part_no, sub_part_no, sub_part_quant, lvl) as (
  select 
    root_part_no, sub_part_no, sub_part_quant, 1
  from tblbom where root_part_no like '132EE%' and isemptyind <> 'Yes'
  union all -- anchor member above; recursive member below
  select
    p.root_part_no, p.sub_part_no, p.sub_part_quant, i.lvl + 1
  from i
  join tblbom p on p.root_part_no = i.sub_part_no
)
select * 
from i
order by lvl, root_part_no, sub_part_no

Обратите внимание на предложение UNION ALL. Он отделяет якорный запрос - выполняется только один раз - от рекурсивного запроса , который выполняется несколько раз для каждой новой строки , полученной в результате, до тех пор, пока больше не производит новых строк. Таким образом, этот запрос может проходить несколько уровней, а не только 2 из них.

Редактировать

Я протестировал запрос выше со следующими (составленными) данными и добавил столбец LVL, чтобы показать рекурсивный уровень:

create table tblbom (
  root_part_no varchar2(10),
  sub_part_no varchar2(10),
  sub_part_quant number(6),
  isemptyind varchar2(10) default 'No'
);

insert into tblbom (root_part_no, sub_part_no, sub_part_quant) values ('132EER', '122FYY', 1);
insert into tblbom (root_part_no, sub_part_no, sub_part_quant) values ('132EER', '766WWW', 2);
insert into tblbom (root_part_no, sub_part_no, sub_part_quant) values ('122FYY', '849ZXA', 3);
insert into tblbom (root_part_no, sub_part_no, sub_part_quant) values ('766WWW', '111111', 4);
insert into tblbom (root_part_no, sub_part_no, sub_part_quant) values ('849ZXA', null, 5);
insert into tblbom (root_part_no, sub_part_no, sub_part_quant) values ('111111', null, 6);

Результат (включая уровень):

ROOT_PART_NO  SUB_PART_NO  SUB_PART_QUANT  LVL
------------  -----------  --------------  ---
132EER        122FYY       1               1  
132EER        766WWW       2               1  
122FYY        849ZXA       3               2  
766WWW        111111       4               2  
111111        <null>       6               3  
849ZXA        <null>       5               3  
...