在Postgres中使用sum进行递归查询

时间:2014-10-30 18:02:51

标签: sql postgresql recursion common-table-expression

我必须在我的数据库中存储很多项目。每个项目都可以有子项目。结构看起来像一棵树:

                                     Project
                            /           |             \
                    ProjectChild1    ProjectChild2    [...]    ProjectChild[n]
                    /       |
 ProjectChildOfChild1    ProjectChildOfChild2

树的等级是未知的。 我想创建一个这样的表:

Projects

project_ID id_unique PRIMARY_KEY
project_NAME text
project_VALUE numeric
project_PARENT id_unique

在这种情况下,列project_PARENT将存储父项目的ID(如果存在)。

对于我的应用程序,我需要检索项目的总值,为此我需要将每个项目子项和根项目的值相加。

我知道我需要使用递归,但我不知道如何在Postgres中这样做。

2 个答案:

答案 0 :(得分:5)

这是@a_horse's correct answer的简化版本(在评论中与OP讨论后) 与递归中的任何(合理有限)级别一起使用。

给定project_id

的总价格
WITH RECURSIVE cte AS (
   SELECT project_id AS project_parent, project_value
   FROM   projects
   WHERE  project_id = 1 -- enter id of the base project here !

   UNION  ALL 
   SELECT p.project_id, p.project_value
   FROM   cte
   JOIN   projects p USING (project_parent)
)
SELECT sum(project_value) AS total_value
FROM   cte;

一次性获得所有项目的总费用:

一次性适用于所有项目

WITH RECURSIVE cte AS (
   SELECT project_id, project_id AS project_parent, project_value
   FROM   projects
   WHERE  project_parent IS NULL  -- all base projects

   UNION  ALL 
   SELECT c.project_id, p.project_id, p.project_value
   FROM   cte c
   JOIN   projects p USING (project_parent)
)
SELECT project_id, sum(project_value) AS total_value
FROM   cte
GROUP  BY 1
ORDER  BY 1;

SQL Fiddle(有正确的测试用例)。

答案 1 :(得分:3)

这样的事情:

with recursive project_tree as (
   select project_id, 
          project_name,
          project_value,
          project_parent
   from projects
   where project_id = 42 -- << the id of the "base" project
   union all 
   select p.project_id,
          p.project_name,
          p.project_value,
          p.project_parent
   from projects p
     join project_tree t on t.project_id = p.project_parent
)
select sum(project_value)
from project_tree;

联盟的第一部分需要选择您要评估的项目(“子”项目)。递归连接将向上走树并检索所有父项目。