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)
对于每种情况,我都需要获得最接近根的节点。意思是:
- 对于W3、W4或W5,我想获取W1的信息(第一次,红蓝)
- 对于 W1,我什么都不想要(或者它拥有信息,可以使用它)
- 对于W0,我什么都不想要
希望我能说清楚。
祝你有个美好的一天。
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"
早上好,
所以我有这种情况: 包含 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)
对于每种情况,我都需要获得最接近根的节点。意思是:
- 对于W3、W4或W5,我想获取W1的信息(第一次,红蓝)
- 对于 W1,我什么都不想要(或者它拥有信息,可以使用它)
- 对于W0,我什么都不想要
希望我能说清楚。 祝你有个美好的一天。
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"