我通过先前的查询进行连接,在Oracle中构建我的树结构。这工作正常,但我有一个组件,需要一个对称的树来正确显示。
所以我的想法是如果节点位于低于最高级别的级别,则向树中注入更多节点。
e.g。如果我们有一棵树
Root
+- Node 1
+- Leaf 1 (Level 3)
+- Node 2
+- Node 3
+- Leaf 2 (Level 4)
我需要在运行时修改树,如下所示:
Root
+- Node 1
+- Copy of Node 1
+- Leaf 1 (Level 4)
+- Node 2
+- Node 3
+- Leaf 2 (Level 4)
这将使我的树在运行时对称,以使组件工作。
是否有一个简单的Oracle查询或函数可以为此提供帮助,或者是否有一些可以帮助解决这个问题的SQL语句?
答案 0 :(得分:1)
好的,经过大量的追踪和错误,我认为我找到了解决方案。
因此,如果您有一个测试表,则将其调用为xx_tree_test,其中包含3个字段:cd,sup_cd和name;我将测试数据添加到它,这个查询
SELECT CD,
SUP_CD,
LEVEL AS LVL,
CASE WHEN CONNECT_BY_ISLEAF = 1 THEN 'L' ELSE NULL END AS LEAF,
LPAD (' ', 3 * LEVEL, ' .') || NAME AS NAME
FROM xx_tree_test
START WITH SUP_CD IS NULL
CONNECT BY PRIOR CD = SUP_CD;
会产生这样的结果:
要添加额外节点以将Leaf 1和Leaf 2置于同一级别,您需要此查询:
SELECT CD,
SUP_CD,
LEVEL AS LVL,
CASE WHEN CONNECT_BY_ISLEAF = 1 THEN 'L' ELSE NULL END AS LEAF,
LPAD (' ', 3 * LEVEL, ' .') || NAME AS NAME
FROM (WITH FULL_TREE
AS ( SELECT CD,
SUP_CD,
LEVEL AS LVL,
CASE
WHEN CONNECT_BY_ISLEAF = 1 THEN 'L'
ELSE NULL
END
AS LEAF,
LPAD (' ', 3 * LEVEL, ' .') || NAME AS TREE_NAME,
NAME
FROM XX_TREE_TEST
START WITH SUP_CD IS NULL
CONNECT BY PRIOR CD = SUP_CD)
SELECT A.NAME,
A.CD,
A.SUP_CD,
A.LVL
FROM FULL_TREE A
WHERE NVL (LEAF, 'z') != 'L'
UNION ALL
SELECT CASE
WHEN TREE1.LVL + TREE2.ROW_NUM_GENERATED - 1 =
(SELECT MAX (LVL) FROM FULL_TREE)
THEN
TREE1.NAME
ELSE
'Copy of ' || TREE1.NAME
END
AS NAME,
CASE
WHEN TREE1.LVL + TREE2.ROW_NUM_GENERATED - 1 =
(SELECT MAX (LVL) FROM FULL_TREE)
THEN
CD
ELSE
CD || '`' || TO_CHAR (TREE2.ROW_NUM_GENERATED)
END
AS CD,
CASE
WHEN TREE2.ROW_NUM_GENERATED = 1 THEN SUP_CD
ELSE CD || '`' || TO_CHAR (TREE2.ROW_NUM_GENERATED - 1)
END
AS SUP_CD,
TREE1.LVL + TREE2.ROW_NUM_GENERATED AS LVL
FROM (SELECT FULL_TREE.NAME,
FULL_TREE.CD,
FULL_TREE.SUP_CD,
FULL_TREE.LVL
FROM FULL_TREE
WHERE LEAF = 'L') TREE1
JOIN
( SELECT LEVEL AS ROW_NUM_GENERATED
FROM DUAL
CONNECT BY LEVEL <= (SELECT MAX (LVL) FROM FULL_TREE)) TREE2
ON (SELECT MAX (LVL) FROM FULL_TREE) + 1 >=
TREE2.ROW_NUM_GENERATED + TREE1.LVL
ORDER BY CD, LVL)
START WITH SUP_CD IS NULL
CONNECT BY PRIOR CD = SUP_CD;
此查询不会产生此结果:
所以现在要做的就是将它打包成一个漂亮的视图来隐藏大量的SQL。
答案 1 :(得分:0)
我不认为它可以在SQL中完成,或者至少我想不出这样做的方法。在我看来,查询必须知道在执行之前需要多少级别。
也许,那么,你需要一个临时表,这样你就可以在你的逻辑中执行第二次传递,以便按照你想要的方式获得它。
您是否有可以显示这些数据的客户端组件?如果是这样,那么这可能是第二次通过的最简单的地方。