sql - 递归计数sql

标签 sql postgresql recursion count

我有这样的表:

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        

我想要这样的表:

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

从 child 到 parent 的计数: 问题是当水费不计入饮用水时,如果纳税或支付水没有支付值(value),则支付所有未计算在内的费用。

最佳答案

我在我们的 postgres 数据库(版本 8.4.22)上试过这个,因为 fiddle 对我来说有点慢。但是可以将 SQL 粘贴到那里,它适用于 postgres。

这里还是fiddle demo第一次大约需要 20 秒,但之后会更快。

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

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) 从上到下处理表中的 ID,从父级为 NULL 的任何 ID 开始。递归部分只是获取父 ID 并将其自己的 ID 添加到其中,以实现您的矩阵树表示字段。

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

现在剩下的就是最后的选择语句。它使用 GROUP BYSUM 将多个可能的子总和值聚合到一行中。

这确实适用于您的特定示例。如果示例数据中未显示不同的情况,则可能会失败,例如,如果具有子项的项目携带需要添加的值。

关于sql - 递归计数sql,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31530061/

相关文章:

javascript - 基于 promise 的递归函数中的问题

MySQL 将列更改为唯一

c++ - C++ 的持久性解决方案(带有 SQL 数据库)?

hibernate - Grails 2.4.4 完全忽略提取 :'join' *使用 PostgreSQL 时*

Javascript getter 和 setter - 递归问题

java - 辅助方法中的递归 (Java)

sql - 如何用 R 分析维基百科文章数据库?

sql - 如何在 "update from select"查询中使用表变量?

python - SQLAlchemy 卡住应用程序

postgresql - 在 Postgresql 中执行更新插入时,ON CONFLICT 子句中未使用部分索引