2015-10-26 73 views
2

早上好之前,的Oracle PL/SQL就根節點查詢

所以我有這樣的情況: 包含數據ID,parentdataID和一些信息

MyTable 
-Name 
-WorkingPeriod 
-ColorScheme 
-ID 
-parentID 

數據表來說明,表這樣的作品:

W0 (Always, Red) 
--W1 (First time, red-blue) 
----W2 (First step, red-blue-grey) 
----W3 (Second step, red-blue-black) 
------W4 (...) 
--------W5 (...) 
--W6 (Second time, red-green) 
----W7 (First step, red-green-grey) 
--W8 (Third time, red-pink) 

我需要,爲每種情況,以獲得最接近的根節點。這意味着:

  • 爲W3,W4和W5,我想W1信息(第一次,紅 - 藍)
  • 爲W1,我想沒有什麼(或者它自己的信息,可以與工作)
  • 對於W0,我什麼都不需要。

希望我能說清楚自己。 祝您有美好的一天。

+0

無採樣數據/表給出一個簡單的查詢,我可能會建議你看SYS_CONNECT_BY_PATH,然後解析它以返回null,如果爲null(W0),則其自身(如果路徑中只有一個節點(W1),或者默認爲第二個節點(Root + 1))返回所有其他情況。 –

+0

@MichaelBroughton我明白你的想法是什麼,但我認爲它不適用於我的情況。我在我的問題中添加了一些細節以使其更易於理解 – Vizul

回答

2

有了充分肯定Pablomatico爲起點,看看這個擴張他的工作是包括對不是2位數字的ID處理,並重新加入到源帶回剛剛纔根排的屬性:

WITH the_table AS (SELECT 'W0' item_id, NULL parent_id, 'Red' colour FROM DUAL 
        UNION 
        SELECT 'W1' item_id, 'W0' parent_id , 'blue' colour FROM DUAL 
        UNION 
        SELECT 'W2' item_id, 'W1' parent_id, 'Grey' colour FROM DUAL 
        UNION 
        SELECT 'W3' item_id, 'W1' parent_id, 'Black' colour FROM DUAL 
        UNION 
        SELECT 'W4' item_id, 'W3' parent_id, 'Mauve' colour FROM DUAL 
        UNION 
        SELECT 'W5' item_id, 'W4' parent_id, 'Orange' colour FROM DUAL 
        UNION 
        SELECT 'W6' item_id, 'W0' parent_id, 'Green' colour FROM DUAL 
        UNION 
        SELECT 'W7' item_id, 'W6' parent_id, 'Grey' colour FROM DUAL 
        UNION 
        SELECT 'W8' item_id, 'W0' parent_id, 'Pink' colour FROM DUAL) 
SELECT main_tab.item_id, main_tab.colour,main_tab.just_before_root, the_Table.colour 
FROM      
(SELECT item_id, 
     colour, 
     SYS_CONNECT_BY_PATH(item_id, '/') node_path, 
     CASE WHEN INSTR(SYS_CONNECT_BY_PATH(item_id, '/'),'/',1,2) = 0 THEN NULL 
      WHEN INSTR(SYS_CONNECT_BY_PATH(item_id, '/'),'/',1,2) != 0 
       AND INSTR(SYS_CONNECT_BY_PATH(item_id, '/'),'/',1,3) = 0 
       THEN SUBSTR(SYS_CONNECT_BY_PATH(item_id, '/'), INSTR(SYS_CONNECT_BY_PATH(item_id, '/'),'/',1,2)+1) 
      ELSE SUBSTR(SYS_CONNECT_BY_PATH(item_id, '/'), INSTR(SYS_CONNECT_BY_PATH(item_id, '/'),'/',1,2)+1,INSTR(SYS_CONNECT_BY_PATH(item_id, '/'),'/',1,3) - INSTR(SYS_CONNECT_BY_PATH(item_id, '/'),'/',1,2) - 1) END just_before_root 
FROM the_table 
CONNECT BY PRIOR item_id = parent_id 
START WITH parent_id IS NULL) main_tab 
left outer join the_table on main_tab.just_before_root = the_table.item_id; 

返回:

ITEM_ID COLOUR JUST_BEFORE_ROOT COLOUR_1 
"W0"  "Red"       
"W1"  "blue" "W1"    "blue"  
"W2"  "Grey" "W1"    "blue"  
"W3"  "Black" "W1"    "blue"  
"W4"  "Mauve" "W1"    "blue"  
"W5"  "Orange" "W1"    "blue"  
"W6"  "Green" "W6"    "Green"  
"W7"  "Grey" "W6"    "Green"  
"W8"  "Pink" "W8"    "Pink"  
+0

這就是它!這對我來說是完美的。謝謝你和@Pablomatico的回答。 – Vizul

0
create or replace function getNodeCloserToRoot 
(
    p_given_node varchar2(50); 
) 
return varchar2 
is 
v_parent_node varchar2(50); 
v_current_node varchar2(50) := p_given_node; 
begin 
    select parentDataId 
    into v_parent_node 
    from MyTable 
    where dataId = v_current_node; 
    loop 
    exit when v_parent_node is null; 
     v_current_node := v_parent_node; 
     select parentDataId 
     into v_parent_node 
     from MyTable 
     where dataId = v_current_node; 
    end loop; 

    return v_current_node; 
end; 
+0

這也是一個好主意。不是我的問題的直接解決方案(但這是我的錯,我的問題不夠明確,我認爲)。但我會保持這一點,它可以幫助我。謝謝 ! – Vizul

2

如前所述,您可以通過分層查詢來完成它。您可以構建每個節點的路徑並從該字符串的根之前提取節點。像這樣的東西可以幫助你得到最終的解決方案:

WITH the_table AS (SELECT 'W0' item_id, NULL parent_id FROM DUAL 
        UNION 
        SELECT 'W1' item_id, 'W0' parent_id FROM DUAL 
        UNION 
        SELECT 'W2' item_id, 'W1' parent_id FROM DUAL 
        UNION 
        SELECT 'W3' item_id, 'W1' parent_id_idrent FROM DUAL 
        UNION 
        SELECT 'W4' item_id, 'W3' parent_id FROM DUAL 
        UNION 
        SELECT 'W5' item_id, 'W4' parent_id FROM DUAL 
        UNION 
        SELECT 'W6' item_id, 'W0' parent_id FROM DUAL 
        UNION 
        SELECT 'W7' item_id, 'W6' parent_id FROM DUAL 
        UNION 
        SELECT 'W8' item_id, 'W0' parent_id FROM DUAL) 
SELECT item_id, 
     SYS_CONNECT_BY_PATH(item_id, '/') node_path, 
     SUBSTR(SYS_CONNECT_BY_PATH(item_id, '/'), 5, 2) just_before_root 
FROM the_table 
CONNECT BY PRIOR item_id = parent_id 
START WITH parent_id IS NULL; 
+0

這個基地已經足夠好了,而且MichaelBroughton加入了這些元素,我能夠解決我的問題。謝謝 ! – Vizul