首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >递归计数sql

递归计数sql
EN

Stack Overflow用户
提问于 2015-07-21 11:52:55
回答 1查看 935关注 0票数 3

我有一张这样的桌子:

代码语言:javascript
复制
id    activity            pay       parent   
1     pay all             -         null     
2     pay tax             10 $      1        
3     pay water bills     -         1        
4     fix house           -         null     
5     fix roof            1 $       4          
6     pay drinking water  1 $       3        

我希望得到这样的表:

代码语言:javascript
复制
id    activity            pay       parent   matriks
1     pay all             {11 $}    null     1       (pay tax + pay water bills)
2     pay tax             10 $      1        1-2
3     pay water bills     {1 $}     1        1-3     (pay drinking water)
4     fix house           {1 $}     null     4       (fix roof)
5     fix roof            1 $       4        4-5     
6     pay drinking water  1 $       3        1-3-6

从孩子到父母的计数:问题是当饮用水中的水费没有计算在内时,如果交税或交水没有支付价值,则支付所有无法计算的费用。

EN

回答 1

Stack Overflow用户

发布于 2015-07-21 17:49:12

我在我们的postgres db (版本8.4.22)上尝试了一下,因为小提琴对我来说有点慢。但是SQL可以粘贴到那里,它可以在postgres上工作。

这里仍然是fiddle demo第一次花了大约20秒,但后来更快。

下面是为我生成计算结果的内容。(我没有根据您的要求对其进行格式化,因为在我看来,主要练习就是计算。)这里假设您的表名为activity

代码语言:javascript
复制
with recursive rekmatriks as(
    select id, activity, pay, parent, id::text as matriks, 0 as lev
        from activity
        where parent is null
    union all
    select activity.id, activity.activity, activity.pay, activity.parent,
           rekmatriks.matriks || '-' || activity.id::text as matriks,
           rekmatriks.lev+1 as lev
        from activity inner join rekmatriks on activity.parent = rekmatriks.id
)
, reksum as (
    select id, activity, pay, parent, matriks, lev, coalesce(pay,0) as subsum
        from rekmatriks
        where not exists(select id from rekmatriks rmi where rmi.parent=rekmatriks.id)
    union all
    select rekmatriks.*, reksum.subsum+coalesce(rekmatriks.pay, 0) as subsum
        from rekmatriks inner join reksum on rekmatriks.id = reksum.parent)

select id, activity, pay, parent, matriks, sum(subsum) as amount, lev
    from reksum
group by id, activity, pay, parent, matriks, lev
order by id

作为额外的好处,这提供了id的嵌套深度。0表示父级,1表示第一个子级,等等。这使用两个递归WITH queries来实现您想要的。所需的计算值位于amount列中。

第一个(rekmatriks)从上到下处理表中的IDs,从父ids为NULL的所有ids开始。递归部分只是简单地获取父id,并将它自己的id添加到它,以获得您的矩阵树表示字段。

第二个(reksum)从下到上工作,从没有子元素的所有行开始。该查询的递归部分为在非递归部分中选择的每个子行选择一个父行,并计算每行的paysubsum之和。这将为每个id生成多个行,因为一个父对象可以有多个子对象。

现在只剩下最后一条select语句了。它使用GROUP BYSUM将多个可能的子求和值聚合到一行中。

这确实适用于您的特定示例。如果样本数据中没有显示不同的情况,那么它可能会失败,例如,如果具有子项的项带有需要添加的值。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31530061

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档