2013-07-10 4 views
3

Мы находимся на Oracle 11g R1. Вот код:Oracle «connect by» - несколько иерархий

CREATE TABLE T1 (ID NUMBER, PARENT_ID NUMBER, LEFT_SIBLING_ID NUMBER); 
INSERT INTO T1 VALUES (1,NULL,NULL); 
INSERT INTO T1 VALUES (3,1,NULL); 
INSERT INTO T1 VALUES (2,1,3); 
INSERT INTO T1 VALUES (4,2,NULL); 
INSERT INTO T1 VALUES (5,2,4); 
INSERT INTO T1 VALUES (10,NULL,1); 
INSERT INTO T1 VALUES (12,10,NULL); 
INSERT INTO T1 VALUES (11,10,12); 

То, что я хотел бы результат быть это:

ID-Tree 
1 
    3 
    2 
     4 
     5 
10 
    12 
    11 

Ключевым моментом здесь является то, что помимо обычного ПРЕДВАРИТЕЛЬНОГО иерархии ID = PARENT_ID, существует другая иерархия основана на ПРЕДВАРИТЕЛЬНОГО ID = LEFT_SIBLING_ID. Дети сортируются в порядке PRIOR ID = LEFT_SIBLING_ID. Вот почему за 3 следуют 2, а 12 на 11 и т. Д. Этот порядок важен.

Я нарисовал пробел о том, как это сделать.

Edit:

Больше строк четко иллюстрируют проблему упорядочения:

CREATE TABLE T1 (ID NUMBER, PARENT_ID NUMBER, LEFT_SIBLING_ID NUMBER); 
INSERT INTO T1 VALUES (1,NULL,10); 
INSERT INTO T1 VALUES (3,1,NULL); 
INSERT INTO T1 VALUES (2,1,3); 
INSERT INTO T1 VALUES (4,2,NULL); 
INSERT INTO T1 VALUES (5,2,4); 
INSERT INTO T1 VALUES (10,NULL,NULL); 
INSERT INTO T1 VALUES (12,10,NULL); 
INSERT INTO T1 VALUES (7,10,12); 
INSERT INTO T1 VALUES (11,10,7); 
INSERT INTO T1 VALUES (6,1,2); 
INSERT INTO T1 VALUES (13,1,6); 
COMMIT; 

Результат запроса:

select substr('----------', 1, lvl*2-2) || to_char(id) id_tree 
from 
(select SYS_CONNECT_BY_PATH(to_char(id,'009'), ':') sort_path, 
     left_sibling_id, id, parent_id, level lvl 
from t1 
start with parent_id is null 
connect by prior id = parent_id) q 
start with left_sibling_id is null 
connect by prior id = left_sibling_id 
and coalesce(parent_id,id) = coalesce(parent_id,id) 
order by case lvl when 1 then sort_path 
        else substr(sort_path,1,length(sort_path)-4) end, 
     level; 

ID_TREE            
-------------------------------------------------- 
1             
--3             
--2             
--6             
--13            
----4            
----5            
10             
--12            
--7             
--11            

11 rows selected 

Хотя братья и сестры упорядочены должным образом (кроме верхнего уровня), они больше не находятся под их родителями.

+0

Есть другие способы сделать заказ братьев и сестер. Вам нужно конкретно использовать этот? –

+0

Вы можете использовать столбец sort_order, а затем использовать 'ORDER SIBLINGS BY sort_order' вместо ссылки на« левый брат ». –

+0

Я не могу изменить таблицу, поэтому мне нужно специально ее использовать. Причина этого пути была выбрана еще раз, когда, как полагали, ускорилось добавление новых идентификаторов. В этой реализации требуется только одна вставка (новый идентификатор) и одно обновление (изменение LEFT_SIBLING_ID одной существующей записи). Если бы был столбец «sort_order», всем сиблям после нового понадобился бы обновленный столбец «sort_order». По крайней мере, это была идея. – SKY

ответ

1

Наконец-то!

Я создал столбец «порядок сортировки» под названием SIBLING_LEVEL ниже, выполнив CONNECT BY на LEFT_SIBLING_ID. Затем я присоединился к оригинальной таблице. Затем по результату этого соединения был сделан простой CONNECT BY ORDER SIBLING BY. Для меня это немного грубая сила, но это все, что я мог придумать.

SELECT ROWNUM, LPAD(' ', (LEVEL*2) - 1, '-') || ID AS HIERARCHY, PARENT_ID, 
LEFT_SIBLING_ID, LEVEL AS PARENT_CHILD_LEVEL 
from 
(
SELECT A.ID, A.PARENT_ID, A.LEFT_SIBLING_ID, B.SIBLING_LEVEL 
FROM 
T1 A 
, 
(
SELECT ID, SUBSTR('----------', 1, LVL*2-2) || TO_CHAR(ID) ID_TREE, 
LEVEL AS SIBLING_LEVEL 
FROM 
(SELECT SYS_CONNECT_BY_PATH(TO_CHAR(ID,'009'), ':') SORT_PATH, 
    LEFT_SIBLING_ID, ID, PARENT_ID, LEVEL LVL 
FROM T1 
START WITH PARENT_ID IS NULL 
CONNECT BY PRIOR ID = PARENT_ID) Q 
START WITH LEFT_SIBLING_ID IS NULL 
CONNECT BY PRIOR ID = LEFT_SIBLING_ID) B 
WHERE A.ID = B.ID 
) C 
START WITH C.PARENT_ID IS NULL 
CONNECT BY PRIOR C.ID = C.PARENT_ID 
ORDER SIBLINGS BY SIBLING_LEVEL; 

http://sqlfiddle.com/#!4/fcd68/5/0