2012-11-02 41 views
8

Đây là phiên bản đơn giản hóa của sự cố mà tôi gặp phải trong PostgreSQL.tổng thứ bậc trong PostgreSQL

Tôi có bảng sau Một:

[IDINTEGER| VALUENUMERIC (10,2)| PHỤ HUYNHINTEGER]

đâu PHỤ HUYNH 'là một tự tham khảo FK ID cột.

Định nghĩa bảng là:

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

bảng đơn giản này cho phép một để xác định cấu trúc dữ liệu cây có chiều sâu tùy ý. Bây giờ tôi cần phải viết một SQL (tôi không thích sử dụng PL-SQL phía máy chủ) báo cáo cho mỗi nút, tổng giá trị của cây con "treo" dưới nó. Ví dụ, với bảng sau:

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

tôi sẽ nhận được kết quả thiết lập sau:

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

cho simplicitly, bạn có thể giả định rằng chỉ có các nút lá có giá trị, các nút lá không luôn luôn có một giá trị của NULL trong cột VALUE. Có cách nào để làm điều này trong SQL, thậm chí sử dụng phần mở rộng cụ thể PostgreSQL?

Trả lời

5

Trong PostgreSQL bạn có thể sử dụng CTE đệ quy (Biểu thức chung) để đi bộ cây trong truy vấn của bạn.

Dưới đây là hai liên kết có liên quan vào các tài liệu:

EDIT

Vì không có subselect cần nó có thể chạy tốt hơn một chút về một tập dữ liệu lớn hơn truy vấn của 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

Có lẽ một cái gì đó như thế này:

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; 

này sẽ bắt đầu với những đứa trẻ mà không có con. Sau đó đi lên cây cho cha mẹ. Kết quả sẽ như sau:

1 3.50 
2 3.50 
3 3.70 
4 3.70 
5 1.50 
6 2.20 
Các vấn đề liên quan