我有这样的表:
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
从孩子到父母的数量: 问题是当水费不计入饮用水时,如果缴纳税款或支付水没有支付价值,则无法支付所有费用。
答案 0 :(得分:2)
我在我们的postgres db(版本8.4.22)上试过这个,因为小提琴对我来说有点慢。但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添加到其中,以实现您的matriks树表示字段。
第二个(reksum
)从下到上工作,并从没有子元素的所有行开始。此查询的递归部分为非递归部分中选择的每个子行选择父行,并计算每行的pay
和subsum
之和。这会为每个id生成多行,因为一个父级可以有多个子级。
现在剩下的就是最后的选择陈述。它使用GROUP BY
和SUM
将多个可能的子总和值聚合到一行中。
这适用于您的特定示例。如果样本数据中未显示不同的情况,则可能会失败,例如,如果包含子项的项目带有需要添加的值。