2015-10-23 99 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