递归计数sql

递归计数sql,sql,postgresql,recursion,count,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 r

我有这样的桌子:

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
我想要这样的桌子:

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
从子项到父项的计数:
问题是,当水费账单没有从饮用水算起时,如果交税或付水费没有支付价值,则“支付全部”无法计算。

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

还是第一次需要20秒的时间,但之后会更快

下面是为我生成计算结果的内容。(我没有按照您的要求设置格式,因为我认为主要的练习是计算。)这假设您的表被称为
活动

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,等等。这使用两个递归来实现您想要的。您需要的计算值位于
金额
列中

第一个(
rekmatriks
)从上到下处理表中的ID,从父项为
NULL
的任何ID开始。递归部分只是获取父id并将其自身的id添加到其中,以实现矩阵树表示字段

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

现在只剩下最后的select语句。它使用
groupby
SUM
将多个可能的子总和值聚合到一行中


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

当您说table时,是指db还是php?如果是db,您使用的是什么RDBMS?那些是什么?什么是矩阵?你的逻辑是什么?@jWeaver在支付饮用水的情况下
1-3-6
我想是因为添加到行
1、3和6
-
支付所有,支付水,支付饮用水
它就像6的父母是3,3的父母是1,所以1-3-6,他应该使用1->3->6clarity@JuanCarlosOropeza我使用postgre,{}孩子的价值,这在右表中解释,例如:支付水费,它让孩子支付饮用水,价值1美元,它对它的父母(支付水费)很好。唯一的问题是格式,不知道OP是否严格按照
{10$}
1(纳税+水费账单)
的方式支付,太好了,这就解决了我的问题!!谢谢大家,谢谢@takrl