2015-10-26 1 views
2

Доброе утро,Oracle PL/SQL Как раз перед корневым узлом запроса

Так я такая ситуация: таблица данных, содержащих dataID, 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 plus 1) для всех остальных случаев. –

+0

@MichaelBroughton Я понимаю, что вы думаете, но я думаю, что это не сработает в моем случае. Я добавил некоторые детали к моему вопросу, чтобы сделать его более понятным. – Vizul

ответ

2

С полной кредит на Pablomatico для начальной точки, посмотрите на это расширение его работы, которая включает в себя обработку для идентификаторов, которые давно не 2-цифры, и повторно присоединяется к источнику, чтобы вернуть атрибуты только что перед тем корневой строки:

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

Смежные вопросы