父母在Oracle

时间:2015-09-17 17:17:57

标签: sql oracle recursion aggregate recursive-query

考虑以下示例结构:

DEPARTMENT

  • ID
  • PARENT_ID
  • NAME
  • 深度

PROJECT

  • ID
  • NAME
  • COST
  • DEPARTMENT_ID

一些数据,仅仅是为了下面的例子:

| ID | PARENT_ID | NAME  | DEPTH |
|----|-----------|-------|-------|
|  1 |      NULL | DEPT1 |     1 |
|  2 |         1 | DEPT2 |     2 |
|  3 |         1 | DEPT3 |     2 |
|  4 |         2 | DEPT4 |     3 |
|  5 |         3 | DEPT5 |     3 |
|  6 |      NULL | DEPT6 |     1 |
|  7 |         6 | DEPT7 |     2 |


|  ID  |  NAME  | COST  | DEPARTMENT_ID |
|------|--------|-------|---------------|
|   1  |  PRJ1  |  100  |      1        |
|   2  |  PRJ2  |  200  |      2        |
|   3  |  PRJ3  |  300  |      3        |
|   4  |  PRJ4  |  400  |      4        |
|   5  |  PRJ5  |  500  |      5        |
|   6  |  PRJ6  |  600  |      6        |
|   7  |  PRJ7  |  700  |      7        |

现在,我需要以某种方式通过一个部门然后由直接子女来汇总项目的成本。

如果选择的过滤器为 DEPT1 ,则意图结果为:

| LINE | DEPARTMENT_ID  | PARENT_ID |  NAME  | AGGREGATE_COST |
|------|----------------|-----------|--------|----------------|
|  1   |       1        |   NULL    |  DEPT1 |           1500 |
|  2   |       2        |     1     |  DEPT2 |            600 |
|  3   |       3        |     1     |  DEPT3 |            800 |

其中:

  • 第3行聚合是PRJ5(DEPT5,DEPT3的子代)+ PRJ3(DEPT3)代价
  • 第2行聚合是PRJ4(DEPT4,DEPT2的子代)+ PRJ2(DEPT2)代价
  • 第1行聚合是他儿童聚合的总和。
  • PRJ6和PRJ7成本被忽略,因为它们来自DEPT6和DEPT7,而那些不在DEPT1的层次结构中(DEPT6将是他的兄弟,而不是孩子)

编辑:

|  ID  |  NAME  | COST  | DEPARTMENT_ID |
|------|--------|-------|---------------|
|   1  |  PRJ1  |   1   |      1        |
|   2  |  PRJ2  |   1   |      1        |
|   3  |  PRJ3  |   1   |      2        |
|   4  |  PRJ4  |   1   |      2        |
|   5  |  PRJ5  |   1   |      4        |

在这种情况下,ivanzg提出的解决方案似乎不起作用。 对于最高级别的项目,我获得了双倍的结果

如果我得到DEPT1的聚合,它会返回类似于此的内容:

| LINE | DEPARTMENT_ID  | PARENT_ID |  NAME  | AGGREGATE_COST |
|------|----------------|-----------|--------|----------------|
|  1   |       1        |   NULL    |  DEPT1 |              8 |
|  2   |       2        |   NULL    |  DEPT1 |              4 |

1 个答案:

答案 0 :(得分:3)

您可以使用CONNECT_BY_ROOT层次结构运算符标记层次结构查询中的行(以便稍后创建组)。在层次结构查询中,通过将所有行根行创建为每个层次结构组合,稍后仅采用并聚合指定的组合。对于您的测试数据,这将返回您指定的内容。

SELECT ROOT_DEPT AS DEPARTMENT_ID
      ,ROOT_PARENT AS PARENT_ID
      ,ROOT_NAME AS NAME
      ,SUM(COST) AS AGGREGATE_COST
FROM (SELECT COST 
            ,CONNECT_BY_ROOT DEPARTMENT_ID ROOT_DEPT 
            ,CONNECT_BY_ROOT PARENT_ID ROOT_PARENT 
            ,CONNECT_BY_ROOT NAME ROOT_NAME
      FROM (SELECT   B.DEPARTMENT_ID
                    ,NVL(A.PARENT_ID,'0') PARENT_ID
                    ,A.NAME
                    ,SUM(B.COST) COST
            FROM  DEPARTMENT A 
                JOIN PROJECT B
                    ON A.ID = B.DEPARTMENT_ID
            --> GROUP COST OF PROJECTS IN THE SAME DEPARTMENT IF THERE ARE ANY
            GROUP BY B.DEPARTMENT_ID
                    ,NVL(A.PARENT_ID,'0')
                    ,A.NAME
            )
        --> MAKE ALL ROWS ROOT ROWS
      CONNECT BY PRIOR DEPARTMENT_ID = PARENT_ID
    )
WHERE ROOT_DEPT = 1 OR ROOT_PARENT  = 1
GROUP BY  ROOT_DEPT
         ,ROOT_PARENT
         ,ROOT_NAME