2011-09-15 46 views
8

我有一個連接通過先前的查詢,在Oracle中建立我的樹結構。這工作正常,但我有一個組件,需要一個對稱的樹來正確顯示。由以前的樹連接必須是對稱的

所以我的想法是如果節點坐落在低於最高級別的級別上,則會向樹中注入更多節點。

例如如果我們有一棵樹

Root 
    +- Node 1 
    +- Leaf 1 (Level 3) 
    +- Node 2 
    +- Node 3 
     +- Leaf 2 (Level 4) 

我需要修改樹在運行時,看起來像這樣:

Root 
    +- Node 1 
    +- Copy of Node 1 
     +- Leaf 1 (Level 4) 
    +- Node 2 
    +- Node 3 
     +- Leaf 2 (Level 4) 

這將使我的樹對稱在運行時組件工作。

是否有一個簡單的Oracle查詢或函數可以幫助這個,或一些SQL語句可以在這方面提供幫助?

回答

0

我不認爲它可以在SQL中完成,或者至少我不能想辦法做到這一點。在我看來,查詢在執行之前必須知道需要多少級別。

也許,你需要一個臨時表,這樣你可以在你的邏輯中執行第二遍以按你想要的方式得到它。

你有一個客戶端組件會顯示這些數據嗎?如果是這樣,那麼這可能是第二次傳球的最簡單的地方。

1

好吧,經過大量的跟蹤和錯誤,我想我找到了解決方案。

所以如果你有一個測試表叫它xx_tree_test有3個字段:cd,sup_cd和name;我添加測試數據給它,該查詢

 SELECT CD, 
      SUP_CD, 
      LEVEL AS LVL, 
      CASE WHEN CONNECT_BY_ISLEAF = 1 THEN 'L' ELSE NULL END AS LEAF, 
      LPAD (' ', 3 * LEVEL, ' .') || NAME AS NAME 
     FROM xx_tree_test 
     START WITH SUP_CD IS NULL 
     CONNECT BY PRIOR CD = SUP_CD; 

會產生這樣的結果:

enter image description here

添加額外的節點,使葉1和葉2到您需要的同等水平此查詢:

SELECT CD, 
      SUP_CD, 
      LEVEL AS LVL, 
      CASE WHEN CONNECT_BY_ISLEAF = 1 THEN 'L' ELSE NULL END AS LEAF, 
      LPAD (' ', 3 * LEVEL, ' .') || NAME AS NAME   
     FROM (WITH FULL_TREE 
       AS ( SELECT CD, 
           SUP_CD, 
           LEVEL AS LVL, 
           CASE 
            WHEN CONNECT_BY_ISLEAF = 1 THEN 'L' 
            ELSE NULL 
           END 
            AS LEAF, 
           LPAD (' ', 3 * LEVEL, ' .') || NAME AS TREE_NAME, 
           NAME 
          FROM XX_TREE_TEST 
        START WITH SUP_CD IS NULL 
        CONNECT BY PRIOR CD = SUP_CD) 
      SELECT A.NAME, 
        A.CD, 
        A.SUP_CD, 
        A.LVL 
       FROM FULL_TREE A 
      WHERE NVL (LEAF, 'z') != 'L' 
      UNION ALL 
      SELECT CASE 
         WHEN TREE1.LVL + TREE2.ROW_NUM_GENERATED - 1 = 
           (SELECT MAX (LVL) FROM FULL_TREE) 
         THEN 
         TREE1.NAME 
         ELSE 
         'Copy of ' || TREE1.NAME 
        END 
         AS NAME, 
        CASE 
         WHEN TREE1.LVL + TREE2.ROW_NUM_GENERATED - 1 = 
           (SELECT MAX (LVL) FROM FULL_TREE) 
         THEN 
         CD 
         ELSE 
         CD || '`' || TO_CHAR (TREE2.ROW_NUM_GENERATED) 
        END 
         AS CD, 
        CASE 
         WHEN TREE2.ROW_NUM_GENERATED = 1 THEN SUP_CD 
         ELSE CD || '`' || TO_CHAR (TREE2.ROW_NUM_GENERATED - 1) 
        END 
         AS SUP_CD, 
        TREE1.LVL + TREE2.ROW_NUM_GENERATED AS LVL 
       FROM (SELECT FULL_TREE.NAME, 
           FULL_TREE.CD, 
           FULL_TREE.SUP_CD, 
           FULL_TREE.LVL 
         FROM FULL_TREE 
         WHERE LEAF = 'L') TREE1 
        JOIN 
         ( SELECT LEVEL AS ROW_NUM_GENERATED 
          FROM DUAL 
         CONNECT BY LEVEL <= (SELECT MAX (LVL) FROM FULL_TREE)) TREE2 
        ON (SELECT MAX (LVL) FROM FULL_TREE) + 1 >= 
         TREE2.ROW_NUM_GENERATED + TREE1.LVL 
      ORDER BY CD, LVL) 
START WITH SUP_CD IS NULL 
CONNECT BY PRIOR CD = SUP_CD; 

沒有這個查詢會產生這樣的結果:

enter image description here

所以現在要做的只是將它打包成一個很好的視圖來隱藏大量的SQL。

相關問題