【问题标题】:Connect by prior tree must be symmetrical通过先验树连接必须是对称的
【发布时间】:2011-09-15 13:28:08
【问题描述】:

我有一个通过先前查询建立的连接,它在 Oracle 中构建了我的树结构。这很好用,但我有一个组件需要对称树才能正确显示。

所以我的想法是如果节点位于低于最高级别的级别,则将更多节点注入树中。

例如如果我们有一棵树

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 语句可以帮助解决这个问题?

【问题讨论】:

    标签: sql oracle


    【解决方案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。

    【讨论】:

      【解决方案2】:

      我不认为它可以在 SQL 中完成,或者至少我想不出一种方法来做到这一点。在我看来,查询在执行之前必须知道预期的级别。

      那么,也许您需要一个临时表,以便您可以在逻辑中执行第二次传递,以按照您想要的方式获取它。

      您有显示这些数据的客户端组件吗?如果是这样,那么这可能是进行第二遍的最简单的地方。

      【讨论】:

        猜你喜欢
        • 2016-11-05
        • 2018-06-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-03-16
        • 2017-12-30
        • 2011-09-09
        • 1970-01-01
        相关资源
        最近更新 更多