2017-11-01 10 views
1

をRESUM私は、データを次ていますcummulativeリセット値との和と

lbid | lbdate  | lbtype  | lbamount 
-----+------------+---------------+--------- 
    1 | 2017-11-01 | Add Plafon |  20 
    2 | 2017-11-02 | Use Balance |  5 
    3 | 2017-11-03 | Add Balance |  1 
    4 | 2017-11-04 | Reduce Plafon |  10 
    5 | 2017-11-06 | Use Balance |  8 
    6 | 2017-11-07 | Add Balance |  2 
    7 | 2017-11-08 | Reduce Plafon |  5 
    8 | 2017-11-10 | Add Plafon |  10 
    9 | 2017-11-11 | Use Balance |  1 
    10 | 2017-11-12 | Reduce Plafon |  5 

基本的に私は期待して最終的な結果は次のようになります。

lbid | lbdate  | lbtype  | lbamount | sumplafon | sumbalance 
-----+------------+---------------+-----------+-----------+------------- 
    1 | 2017-11-01 | Add Plafon |  20 |  20 |  20 
    2 | 2017-11-02 | Use Balance |  5 |  20 |  15 
    3 | 2017-11-03 | Add Balance |  1 |  20 |  16 
    4 | 2017-11-04 | Reduce Plafon |  10 |  10 |  10 
    5 | 2017-11-06 | Use Balance |  8 |  10 |   2 
    6 | 2017-11-07 | Add Balance |  2 |  10 |   4 
    7 | 2017-11-08 | Reduce Plafon |  5 |  5 |   4 
    8 | 2017-11-10 | Add Plafon |  10 |  15 |  14 
    9 | 2017-11-11 | Use Balance |  1 |  15 |  15 
    10 | 2017-11-12 | Reduce Plafon |  5 |  10 |  10 

sumplafonはlbtypeが追加されているすべてのlbamountの合計です残高(プラス)と残高を減らす(マイナス、sumplafonを減算する)。

私はすでにこれを行っていました。

sum(
    case 
     when "lbtype" = 'Add Plafon' then "lbamount" 
     when "lbtype" = 'Reduce Plafon' then -1 * "lbamount" 
     else 0 
    end 
) over (order by "lbdate") sumplafon 

そしてsumbalanceは、Plafon(ポジティブ)を追加使用残高(ポジティブ)、利用残高(負)が、Plafonを削減lbtypeたびに発見され、sumbalanceがリセットされますされているlbtypeすべてlbamountの合計ですumbalanceがsumplafonより大きい場合はsumplafonに設定します。

たとえば、lbtypeがReduce Plafonで、渋滞度が16でsumplafon10より大きい場合、渋滞をsumplafon = 10にリセットしてから、umbalanceの合計を再計算する必要があります。

このようなカウントで最初にグループを準備してみました。

count(
    case when "lbtype" = 'Reduce Plafon' then 1 else null end 
) over (order by "lbdate") countplafon 

した後、第2のCTEに、私はこのように、最初のCTEのcountplafonでパーティションを使用して合計をした:

sum(
    case 
     when "lbtype" = 'Add Plafon' or "lbtype" = 'Add Balance' then "lbamount" 
     when "lbtype" = 'Use Balance' then -1 * "lbamount" 
     else 0 
    end 
) over (partition by "countplafon" order by "lbdate") sumbalance 

しかし、それは使用しているので、結果がちょうど最初からsumbalanceをリセットされますcountplafonでグループ化する。

lbid | lbdate  | lbtype  | lbamount | countplafon |sumplafon | sumbalance 
-----+------------+---------------+-----------+-----------+-------------|----------- 
    1 | 2017-11-01 | Add Plafon |  20 |   0 |  20 |  20 
    2 | 2017-11-02 | Use Balance |  5 |   0 |  20 |  15 
    3 | 2017-11-03 | Add Balance |  1 |   0 |  20 |  16 
    4 | 2017-11-04 | Reduce Plafon |  10 |   1 |  20 |   0 
    5 | 2017-11-06 | Use Balance |  8 |   1 |  20 |  -8 
    6 | 2017-11-07 | Add Balance |  2 |   1 |  20 |  -6 
    7 | 2017-11-08 | Reduce Plafon |  5 |   2 |  20 |   0 
    8 | 2017-11-10 | Add Plafon |  10 |   2 |  20 |  10 
    9 | 2017-11-11 | Use Balance |  1 |   2 |  20 |   9 
    10 | 2017-11-12 | Reduce Plafon |  5 |   3 |  20 |   0 

ここにはsqlfiddleがあります。

ここにSQLがあります。

with 
    cte_runningnumbers1 
    as (
     select 
      "lbid", 
      "lbdate", 
      "lbtype", 
      "lbamount", 
      count(
       case when "lbtype" = 'Reduce Plafon' then 1 else null end 
      ) over (order by "lbdate") countplafon, 
      sum(
       case 
        when "lbtype" = 'Add Plafon' then "lbamount" 
        when "lbtype" = 'Reduce Plafon' then -1 * "lbamount" 
        else 0 
       end 
      ) over (order by "lbdate") sumplafon 
     from "lb" 
    ), 
    cte_runningnumbers2 as (
     select 
      *, 
      sum(
       case 
        when "lbtype" = 'Add Plafon' or "lbtype" = 'Add Balance' then "lbamount" 
        when "lbtype" = 'Use Balance' then -1 * "lbamount" 
        else 0 
       end 
      ) over (partition by "countplafon" order by "lbdate") sumbalance 
     from "cte_runningnumbers1" 
    ) 
select * 
from cte_runningnumbers2 

私はこのSO questionに従っていましたが、私はまだ私の問題を解決する方法を混同しています。

私がする必要がある最後のステップは、前回の揺らぎまたはsumplafon(sumumbafanceがsumplafonより大きい場合)を追加することですが、それを行う方法はわかりません。誰でも助けてくれますか?

答えて

1

状態遷移関数のロジックcustom aggregate function.場所を作成します。

create or replace function lb_agg_fun(sumbalance numeric, lbtype text, lbamount numeric) 
returns numeric language sql as $$ 
    select case 
     when lbtype in ('Add Plafon', 'Add Balance') then sumbalance + lbamount 
     when lbtype = 'Use Balance' then sumbalance - lbamount 
     else case 
      when lbamount < sumbalance then lbamount 
      else sumbalance 
     end 
    end; 
$$; 

Create an aggregate:

create aggregate lb_agg(text, numeric) (
    sfunc = lb_agg_fun, 
    stype = numeric, 
    initcond = 0 
); 

そして、それを使用します。

select *, lb_agg(lbtype, lbamount) over (order by lbdate) as sumbalance 
from lb; 

lbid | lbdate | lbtype  | lbamount | sumbalance 
------+------------+---------------+----------+------------ 
    1 | 2017-11-01 | Add Plafon |  20 |   20 
    2 | 2017-11-02 | Use Balance |  5 |   15 
    3 | 2017-11-03 | Add Balance |  1 |   16 
    4 | 2017-11-04 | Reduce Plafon |  10 |   10 
    5 | 2017-11-06 | Use Balance |  8 |   2 
    6 | 2017-11-07 | Add Balance |  2 |   4 
    7 | 2017-11-08 | Reduce Plafon |  5 |   4 
    8 | 2017-11-10 | Add Plafon |  10 |   14 
    9 | 2017-11-11 | Use Balance |  1 |   13 
    10 | 2017-11-12 | Reduce Plafon |  5 |   5 
(10 rows)