3

Oracle 11g R1 を使用しています。コードは次のとおりです。

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

ここで重要なのは、通常の PRIOR ID = PARENT_ID 階層の他に、PRIOR ID = LEFT_SIBLING_ID に基づく別の階層があることです。子は、PRIOR ID = LEFT_SIBLING_ID の順にソートされます。そのため、3 の後に 2 が続き、12 の後に 11 が続きます。この順序は重要です。

これを行う方法について空白を描きました。

編集:

順序付けの問題を明確に示すために、さらに行を追加します。

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

兄弟は適切に並べられていますが (トップ レベルを除く)、もはや親のすぐ下にはありません。

4

1 に答える 1

2

ついに!

LEFT_SIBLING_ID で CONNECT BY を実行して、以下の SIBLING_LEVEL という名前の「並べ替え順序」列を作成しました。次に、それを元のテーブルに結合しました。次に、その結​​合の結果に対して、単純な 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

于 2013-07-10T19:18:28.257 に答える