Oracle - Как использовать объединение в иерархическом запросе и избегать декартового произведения - PullRequest
0 голосов
/ 06 сентября 2018

У меня есть требование выбрать данные из двух таблиц - сначала хранятся данные иерархии (STR таблица), а другая, скажем, начальные точки иерархии (REQ таблица), и мне нужно выбрать иерархию и объединить ее с другим столбцом из REQ таблицы.

Вот пример:

CREATE TABLE REQ (prop int,          ord  varchar2(10));
CREATE TABLE STR (par  varchar2(10), chld varchar2(10));

INSERT INTO REQ VALUES (100,'A');
INSERT INTO REQ VALUES (101,'A');
INSERT INTO REQ VALUES (102,'B');
INSERT INTO STR VALUES ('A','A1');
INSERT INTO STR VALUES ('A','A2');
INSERT INTO STR VALUES ('A1','A3');
INSERT INTO STR VALUES ('A2','A5');
INSERT INTO STR VALUES ('A3','A6');
INSERT INTO STR VALUES ('B','B1');
INSERT INTO STR VALUES ('B','B2');

Базовый запрос из таблицы STR дает, например, эту иерархию:

SELECT par, chld, level
FROM STR
CONNECT BY PRIOR chld = par
START WITH PAR IN (SELECT ord FROM REQ WHERE prop = 100);

Иерархия в порядке:

PAR        CHLD            LEVEL
---------- ---------- ----------
A          A1                  1
A1         A3                  2
A3         A6                  3
A          A2                  1
A2         A5                  2

Мне нужно добавить в результат значение столбца prop из таблицы REQ. Я ожидаю получить такой результат:

PAR        CHLD            LEVEL  PROP 
---------- ---------- ---------- ----- 
A          A1                  1   100   
A1         A3                  2   100
A3         A6                  3   100
A          A2                  1   100
A2         A5                  2   100

Когда я пытаюсь объединить обе таблицы в JOIN и CONNECT BY, я получаю что-то вроде декартового произведения, некоторые строки дублируются:

SELECT STR.par, STR.chld, level, REQ.prop, REQ.ord
FROM STR
,    REQ
WHERE REQ.prop = 100
CONNECT BY PRIOR STR.chld = STR.par
START WITH STR.PAR = REQ.ord;

Результат НЕ тот, который я хотел бы получить:

PAR        CHLD            LEVEL       PROP ORD      
---------- ---------- ---------- ---------- ----------
A          A1                  1        100 A         
A1         A3                  2        100 A         
A3         A6                  3        100 A         
A3         A6                  3        100 A        ! extra
A3         A6                  3        100 A        ! rows !
A1         A3                  2        100 A        !
A3         A6                  3        100 A        ! 
A3         A6                  3        100 A        ! 
A3         A6                  3        100 A        ! 
A          A2                  1        100 A         
A2         A5                  2        100 A         
A2         A5                  2        100 A        ! 
12 rows selected 

Есть ли способ исправить запрос, чтобы получить ожидаемые данные?

Ответы [ 2 ]

0 голосов
/ 07 сентября 2018

Я нашел другой способ - не знаю, идеален ли он, но, похоже, он работает:

SELECT STR.par, STR.chld, level, REQ.prop, REQ.ord
FROM STR
,    REQ
CONNECT BY PRIOR STR.chld = STR.par
AND        PRIOR REQ.prop = REQ.prop
START WITH STR.PAR = REQ.ord AND REQ.prop = 100;
0 голосов
/ 06 сентября 2018

Следующий запрос должен помочь - не знаю, идеален ли он, но он будет работать:

SELECT DISTINCT STR.par, STR.chld, level
     , connect_by_root req.prop AS prop
     , connect_by_root req.ord AS ord
  FROM str
  LEFT JOIN REQ
    ON REQ.ord = str.par
CONNECT BY PRIOR STR.chld = STR.par
  START WITH REQ.prop = 100
...