Postgre / SQL查询与递归

时间:2015-10-23 21:56:05

标签: sql postgresql recursion circular-dependency

我正在尝试创建某个SQL查询。首先,这里是ER图和我创建的表:

enter image description here

CREATE TABLE Course (
    CNr INTEGER PRIMARY KEY NOT NULL,
    costs NUMERIC(7, 2) NOT NULL
);

CREATE TABLE requires (
    pred INTEGER REFERENCES Course(CNr),
    succ INTEGER REFERENCES COURSE(CNr),
    PRIMARY KEY(pred, succ)
);

带有值的表格如下所示:

|   Course    |  |   requires  |
|-------------|  |-------------|
| CNr | costs |  | pred | succ |
|-----|-------|  |------|------|
|  1  |  100  |  |  1   |  2   |
|  2  |  200  |  |  1   |  3   |
|  3  |  300  |  |  2   |  3   |
|  4  |  400  |  |  3   |  4   |

我需要的是返回课程的CNr及其本身的费用加上所有前任课程的总和。使用给定的表格,它看起来像这样:

| CNr | total |
|-----|-------|
|  1  |  100  |
|  2  |  300  |
|  3  |  600  |
|  4  |  1000 |

我遗漏了循环条目,因为在这种情况下它确实没有意义(如果它们按循环顺序进行,它们真的无法进行),所以我'我不确定你是否也必须寻找。 这应该与WITH RECURSIVE在某种程度上是可行的,但我老实说不知所措。有人至少可以指出我正确的方向吗?

2 个答案:

答案 0 :(得分:3)

您可以使用递归CTE执行此操作:

with recursive cte as (
      select pred, succ
      from requires r
      union all
      select cte.pred, r.succ
      from cte join
           requires r
           on cte.succ = r.pred
     )
select c.cnr, coalesce(sum(cpred.costs), 0) + c.costs
from course c left join
     (select distinct * from cte) cte
     on c.cnr = cte.succ left join
     course cpred
     on cte.pred = cpred.cnr
group by c.cnr, c.costs;

Here是一个SQL小提琴。

答案 1 :(得分:1)

首先尝试这个简单的查询,看看你得到了什么:

SELECT
    CNr
    , COALESCE(
    (
        SELECT SUM( costs )
        FROM Course cr
        WHERE CNr IN (
            SELECT pred 
            FROM requires r
            WHERE r.succ = c.CNr
        )
    )
    , 0 )::INTEGER + costs AS total
FROM Course c