2015-10-23 95 views
2

我试图创建一个特定的SQL查询。首先,这里的ER图和我创建的表:递归Postgre/SQL查询

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以及自身的成本加上所有前身课程的总和。在给定的表,它768,16这个样子:

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

我已经离开了圆形的条目,因为它并没有真正意义在这种情况下,(真的不能永远做一个疗程,如果他们在去循环订单),所以我不确定你是否也需要查找。 这应该在某种程度上与WITH RECURSIVE一起完成,但我诚实地处于亏损状态。至少有人能指出我朝着正确的方向吗?

回答

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小提琴。

+0

谢谢!然而,有人可以解释发生在合并(和(cpred.costs),0)+ c.costs 部分中的情况吗?我想我错过了某些东西。 – skulpt

+0

这只是将当前课程的成本加到前辈的成本中。如果没有,前面的总和就是“NULL”。 –

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 
+0

谢谢,然而,结果是: 1 - NULL 2 - 100 3 - 300 4 - 300 – skulpt

+0

请重新检查编辑。现在应该很好地工作 – CAllen

+0

也应该在你的例子中应该= 700没有1000 – CAllen