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

Oracle PL/SQL Just before root node query

早上好,

所以我有这种情况: 包含 dataID、parentdataID 和一些信息的 table 数据

MyTable
-Name
-WorkingPeriod
-ColorScheme
-ID
-parentID

为了说明,table 是这样工作的:

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)

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

希望我能说清楚。 祝你有个美好的一天。

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;

如前所述,您可以通过分层查询来完成。您可以构建每个节点的路径,并从该字符串的根节点之前提取节点。这样的事情可能会帮助您获得最终解决方案:

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;

起点完全归功于 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;

Returns:

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"