当前位置: 首页 > 知识库问答 >
问题:

递归SQL:使用递归子查询分解的聚合函数

陈奇希
2023-03-14

表T表示树。每个记录都是一个节点,每个节点只有一个父节点。

该查询计算每个节点的每个分支的SUM()。

WITH t AS
        (SELECT  1 id, NULL parent_id, NULL value FROM dual UNION ALL
         SELECT 10 id,    1 parent_id, 1000 value FROM dual UNION ALL
         SELECT 20 id,    1 parent_id, 2000 value FROM dual UNION ALL
         SELECT 30 id,   10 parent_id, 3000 value FROM dual UNION ALL
         SELECT 40 id,   10 parent_id, 4000 value FROM dual UNION ALL
         SELECT 50 id,   20 parent_id, 5000 value FROM dual UNION ALL
         SELECT 60 id,    1 parent_id, 6000 value FROM dual UNION ALL
         SELECT 70 id,   60 parent_id, 7000 value FROM dual UNION ALL
         SELECT 80 id,   70 parent_id, 8000 value FROM dual
    ) SELECT CAST(LPAD(' ', (LEVEL-1)*4) || ID AS VARCHAR2(20))  id
        ,VALUE                                                   self_value
        ,(SELECT SUM (value)
          FROM   t t2
          CONNECT BY 
            PRIOR t2.ID = t2.parent_id
            START WITH t2.id = t.id)                             branch_value
      FROM   t
      CONNECT BY PRIOR t.id = t.parent_id
      START WITH t.parent_id IS NULL
      ORDER SIBLINGS BY t.id;
ID                   SELF_VALUE BRANCH_VALUE
-------------------- ---------- ------------
1                                      36000
    10                     1000         8000
        30                 3000         3000
        40                 4000         4000
    20                     2000         7000
        50                 5000         5000
    60                     6000        21000
        70                 7000        15000
            80             8000         8000

9 rows selected.

我一直在尝试使用替代的子查询分解语法来实现这个查询的相同结果。任何帮助都将不胜感激!

共有1个答案

孔棋
2023-03-14

在递归查询中支持groupby之前,我认为只有一个查询是不可能的。因此,我在WITH-子句中添加了第二个子查询。也许这就足够解决你的问题了(好的脑筋急转弯)。

这将计算数据:

WITH t AS
        (SELECT  1 id, NULL parent_id, NULL value FROM dual UNION ALL
         SELECT 10 id,    1 parent_id, 1000 value FROM dual UNION ALL
         SELECT 20 id,    1 parent_id, 2000 value FROM dual UNION ALL
         SELECT 30 id,   10 parent_id, 3000 value FROM dual UNION ALL
         SELECT 40 id,   10 parent_id, 4000 value FROM dual UNION ALL
         SELECT 50 id,   20 parent_id, 5000 value FROM dual UNION ALL
         SELECT 60 id,    1 parent_id, 6000 value FROM dual UNION ALL
         SELECT 70 id,   60 parent_id, 7000 value FROM dual UNION ALL
         SELECT 80 id,   70 parent_id, 8000 value FROM dual),
hierarchy (id,ancestor,value) AS (
  SELECT t.id,t.id,t.value
    FROM t
  UNION ALL
  SELECT t.id,h.ancestor,t.value
    FROM t
      INNER JOIN hierarchy h
        ON t.parent_id = h.id)
SELECT h.ancestor, t.parent_id, t.value, SUM(h.value)
  FROM hierarchy h
    INNER JOIN t
      ON t.id = h.ancestor
  GROUP BY h.ancestor,t.value,t.parent_id;

要获得与问题中所述相同的顺序和格式,请添加路径和深度计算:

WITH t AS
        (SELECT  1 id, NULL parent_id, NULL value FROM dual UNION ALL
         SELECT 10 id,    1 parent_id, 1000 value FROM dual UNION ALL
         SELECT 20 id,    1 parent_id, 2000 value FROM dual UNION ALL
         SELECT 30 id,   10 parent_id, 3000 value FROM dual UNION ALL
         SELECT 40 id,   10 parent_id, 4000 value FROM dual UNION ALL
         SELECT 50 id,   20 parent_id, 5000 value FROM dual UNION ALL
         SELECT 60 id,    1 parent_id, 6000 value FROM dual UNION ALL
         SELECT 70 id,   60 parent_id, 7000 value FROM dual UNION ALL
         SELECT 80 id,   70 parent_id, 8000 value FROM dual),
hierarchy (id,ancestor,value,depth,path) AS (
  SELECT t.id,t.id,t.value,0,''||t.id
    FROM t
  UNION ALL
  SELECT t.id,h.ancestor,t.value,h.depth+1,h.path||'.'||t.id
    FROM t
      INNER JOIN hierarchy h
        ON t.parent_id = h.id)
SELECT LPAD(h.ancestor,p.depth*4+1,' ') AS id, t.value AS self_value, SUM(h.value) as branch_value
  FROM hierarchy h
    INNER JOIN t
      ON t.id = h.ancestor
    INNER JOIN (SELECT id,depth,path
                  FROM hierarchy
                  WHERE ancestor IN (SELECT id FROM t WHERE parent_id IS NULL)
                  ORDER BY path) p
      ON p.id = t.id
  GROUP BY h.ancestor,t.value,t.parent_id,p.path,p.depth
  ORDER BY p.path;
 类似资料:
  • 问题内容: 基于现有表,我使用了CTE递归查询来得出以下数据。但是无法进一步应用它。 数据如下 我想从上述数据递归形成完整路径。意味着递归将给出以下输出。 谢谢 问题答案: 以下是CTE的示例:

  • 问题内容: 我们如何在T-SQL中编写递归SQL查询?您能举一个这样的递归sql查询的简单例子吗? 问题答案:

  • 问题内容: 我有一组按层次结构组织的数据,应该可以增长到任意大小。我需要检索整个树,但是我无法弄清楚如何仅使用SQL来完成。我当前的解决方案是创建一个临时表,并使用递归函数依次查询树的分支,然后将结果存储在临时表中,随后我再次对其进行查询以产生所需的结果。 我的问题是,从本质上讲,我正在执行的联接正确吗?构造一个中间表,然后查询结果。似乎应该有一种使用联接的方法,但是MySQL文档仅涵盖检索有限深

  • 问题内容: JPA 2是否具有运行递归查询的任何机制? 这是我的情况:我有一个实体E,其中包含一个整数字段x。它还可能具有通过@OneToMany映射的E类型的子代。我想做的是通过主键找到一个E,并获取其x的值以及所有后代的x值。有没有办法在单个查询中执行此操作? 我正在使用Hibernate 3.5.3,但我不希望在Hibernate API上没有任何明确的依赖关系。 编辑:根据这一项目,Hib

  • 本文向大家介绍Oracle Database 使用递归子查询分解子句拆分字符串,包括了Oracle Database 使用递归子查询分解子句拆分字符串的使用技巧和注意事项,需要的朋友参考一下 示例 样本数据: 查询: 输出:            

  • 问题内容: 我在此处查看了Tim Hall的精彩文章,该文章允许您使用自引用实体并使用Oracle中的CTE语法显示分层数据(从顶级节点开始,然后递归返回)。 所以我有看起来像这样的代码: 对于锚行(SQL中的顶层层次结构J1条目,其父级为NULL),我想: 对于递归联接: 如果尝试在UNION ALL语句上方添加ORDER BY语句,则会得到某种无效的SQL语法。 您如何解决此问题,以便最后按层