我有这样的表:
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
) 从下到上工作,从没有子元素的所有行开始。此查询的递归部分为在非递归部分中选择的每个子行选择父行,并计算每行的 pay
和 subsum
的总和。这会为每个 ID 生成多行,因为一个父项可以有多个子项。
现在剩下的就是最后的选择语句。它使用 GROUP BY
和 SUM
将多个可能的子总和值聚合到一行中。
这确实适用于您的特定示例。如果示例数据中未显示不同的情况,则可能会失败,例如,如果具有子项的项目携带需要添加的值。
关于sql - 递归计数sql,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31530061/