2012-11-02 60 views
8

這是我在PostgreSQL中遇到的問題的簡化版本。PostgreSQL中的分層和

我有以下表

[IDINTEGER| VALUENUMERIC(10,2)| PARENTINTEGER]

在哪裏 '父' 是一個自引用FK到列ID。

表定義爲:

CREATE TABLE A(ID INTEGER IDENTITY, VALUE NUMERIC(10,2), PARENT INTEGER)          
ALTER TABLE A ADD CONSTRAINT FK FOREIGN KEY (PARENT) REFERENCES A(ID) 

這個簡單的表允許定義任意深度的樹數據結構。現在我需要編寫一個報告每個節點的SQL(我寧願不使用服務器端PL-SQL),在其下面填充子樹的總數值。例如,下表:

| ID | VALUE | PARENT | 
------------------------- 
| 1 | NULL | NULL | 
| 2 | 3.50 | 1 | 
| 3 | NULL | NULL | 
| 4 | NULL | 3 | 
| 5 | 1.50 | 4 | 
| 6 | 2.20 | 4 | 

我應該得到以下結果集:

| ID | Total-Value-of-Subtree | 
| 1 |     3.50 | 
| 2 |     3.50 | 
| 3 |     3.70 | 
| 4 |     3.70 | 
| 5 |     1.50 | 
| 6 |     2.20 | 

對於simplicitly,你可以假設,只有葉節點有值,非葉節點總是有值NULLVALUE列中。有沒有辦法在SQL中做到這一點,即使利用PostgreSQL特定的擴展?

回答

5

在PostgreSQL中,您可以使用遞歸CTE(公用表表達式)在查詢中遍歷樹。

這裏有兩個相關鏈接中的文檔:

編輯

因爲這裏不需要再選擇它可能運行好一點比Arion的查詢更大的數據集。

WITH RECURSIVE children AS (
    -- select leaf nodes 
    SELECT id, value, parent 
     FROM t 
     WHERE value IS NOT NULL 
    UNION ALL 
    -- propagate values of leaf nodes up, adding rows 
    SELECT t.id, children.value, t.parent 
     FROM children JOIN t ON children.parent = t.id 
) 
SELECT id, sum(value) 
    FROM children 
    GROUP BY id -- sum up appropriate rows 
    ORDER BY id; 
5

也許是這樣的:

WITH RECURSIVE CTE 
AS 
(
    SELECT 
     t.ID, 
     t.VALUE, 
     t.PARENT 
    FROM 
     t 
    WHERE NOT EXISTS 
     (
      SELECT NULL FROM t AS t2 WHERE t2.PARENT=t.ID 
     ) 
    UNION ALL 
    SELECT 
     t.ID, 
     COALESCE(t.VALUE,CTE.VALUE), 
     t.PARENT 
    FROM 
     t 
     JOIN CTE 
      ON CTE.PARENT=t.ID 
) 
SELECT 
    CTE.ID, 
    SUM(CTE.VALUE) 
FROM 
    CTE 
GROUP BY 
    CTE.ID 
ORDER BY 
    ID; 

這將啓動與沒有孩子的孩子。然後上樹到父母身邊。結果將如下所示:

1 3.50 
2 3.50 
3 3.70 
4 3.70 
5 1.50 
6 2.20