2015-07-21 71 views
3

我的表是這樣的:遞歸數SQL

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

當你說表時,你的意思是db或php?如果db你使用的是什麼RDBMS?那些'{}'是什麼? –

+0

什麼是matriks?你的邏輯是什麼? – Ravi

+0

@jWeaver在支付飲用水'1-3-6'的情況下,我認爲是因爲增加了行'1,3和6' - '付全部,付水,付飲料' –

回答

2

我在我們的postgres db(版本8.4.22)上試過這個,因爲小提琴對我的口味有點慢。但SQL可以粘貼在那裏,它適用於postgres。

這裏仍然是fiddle demo第一次需要20秒,但後來更快。

下面是爲我生成計算結果的原因。 (我沒有按照您的要求格式化,因爲在我的腦海裏的主要是鍛鍊; Tibial計算)。這是假設你的表稱爲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)從下到上工作,並從沒有子元素的所有行開始。此查詢的遞歸部分爲非遞歸部分中選定的每個子行選擇一個父行,並計算每行的paysubsum的總和。這會爲每個ID生成多行,因爲一個父級可以有多個子級。

現在剩下的就是最終的選擇聲明。它使用GROUP BYSUM將多個可能的子和值整合到一行中。

這對您的特定示例有效。如果樣本數據中沒有顯示不同的情況,則可能會失敗,例如,如果具有子女的項目帶有需要添加的值。

+0

非常好。唯一的是格式,不知道OP是否非常嚴格把付款作爲'{10 $}'和matriks作爲'1(付稅+付水費)' –

+0

哦......太好了,解決了我的問題!感謝所有,謝謝@takrl – alpiopio