Oracle PL / SQL就在根节点查询之前

时间:2015-10-26 14:42:51

标签: oracle plsql hierarchical-data

早上好,

所以我遇到这种情况: 包含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)

对于每种情况,我都需要获得最接近root的节点。意思是:

  • 对于W3,W4或W5,我想获得W1信息(第一次,红蓝)
  • 对于W1,我什么都不想(或者它自己的信息,可以使用它)
  • 对于W0,我什么都不想。

希望我能够让自己清楚。 祝你有个美好的一天。

3 个答案:

答案 0 :(得分: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;

答案 1 :(得分:2)

完全归功于Pablomatico的起点,看看他的工作的扩展,包括处理不是2位数字的ID,并重新加入源以恢复之前的属性 - 根行:

convert

返回:

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;

答案 2 :(得分: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;