2012-09-06 37 views
2

树无限深。例如:postgresql计数子女数

+----+-------+--------------------+ 
| id | name | parent_id | value | 
+----+-------+--------------------+ 
| 1 | test1 |   | 0 | 
| 2 | test2 |  1  | 0 | 
| 3 | test3 |  2  | 5 | 
| 4 | test4 |  1  | 0 | 
| 5 | test5 |  4  | 5 | 
| 6 | test6 |  4  | 0 | 
| 7 | test7 |  6  | 10 | 
+----+-------+--------------------+ 

我想获得一个孩子的总价值。 就像这样:

+----+-------+--------------------+ 
| id | name | parent_id | value | 
+----+-------+--------------------+ 
| 1 | test1 |   | 20 | = test2.value + test4.value 
| 2 | test2 |  1  | 5 | = test3.value 
| 3 | test3 |  2  | 5 | 
| 4 | test4 |  1  | 15 | = test5.value + test6.value 
| 5 | test5 |  4  | 5 | 
| 6 | test6 |  4  | 10 | = test7.value 
| 7 | test7 |  6  | 10 | 
+----+-------+--------------------+ 

有什么建议吗?谢谢!

+0

不知道你需要休息,我不能说什么明确的关于什么是正确的模式是,但你的实现是树木存储在数据库中一个非常原始的方法。一些设计模式已经被发明出来,可以更轻松地做各种巧妙的事情,包括你问的问题。例如,查看物化路径设计模式。请参阅http://www.rampant-books.com/book_0601_sql_coding_styles.htm或其他参考资料。 –

+0

@ hims056:什么不清楚?遵循'parent_id'链接并递归求和'count'值。 –

+0

@ hims056第一张桌子是我的,第二张是我想要创建的视图 – Danfi

回答

11

这里是希望能解决您的问题递归查询:

WITH RECURSIVE tree (id, parent_id, cnt) AS (
    -- start from bottom-level entries 
    SELECT id, parent_id, 0::bigint AS cnt 
    FROM tbl t 
    WHERE NOT EXISTS (
     SELECT id 
     FROM tbl 
     WHERE parent_id = t.id 
    ) 

    UNION ALL 

    -- join the next level, add the number of children to that of already counted ones 
    SELECT t.id, t.parent_id, tree.cnt + (
      SELECT count(id) 
      FROM tbl 
      WHERE parent_id = t.id 
     ) 
    FROM tbl t JOIN tree ON t.id = tree.parent_id 
) 
SELECT tree.id, max(tree.cnt) AS number_of_children 
FROM tree 
-- use the JOIN if you need additional columns from tbl 
-- JOIN tbl ON tree.id = tbl.id 
-- use the WHERE clause if you want to see root nodes only 
-- WHERE parent_id IS NULL 
GROUP BY tree.id 
ORDER BY tree.id 
; 

我做了一个SQLFiddle了。

+0

谢谢你的回答。我犯了一个错误,我真的想得到总价值,但不是数量。抱歉。 – Danfi

+0

最后我用函数来解决它。 – Danfi

+0

恐怕你的实现不正确。请考虑一棵树有一个有三个孩子的根,两个首先有两个孩子,最后一个没有孩子。根据你的查询,根有5个孩子(后代),而实际上它有7个。 – lared