2016-10-22 24 views
1

各行にid(key)、date、sign、valueという名前のフィールドを持つテーブルがあります。リセット条件付きのMysqlの累積合計、期間別グループ

Sign = 0はリセット条件です。初期累積値の設定に使用されます。

Sign = +1は追加条件です。それは累積合計に値を加算します。

Sign = -1は減算であり、推測するように、累積合計は減少します。

順序は重要なので、0、1、-1の順序で評価する必要があります。

私は値の累積合計を取得したいとしましょう。

SELECT my_date, my_sign, my_value, @cum AS cum_before, 
(@cum := IF(my_sign !=0, @cum + my_sign * my_value, my_value)) AS cum_after 
FROM my_table, (SELECT @cum :=0) as t WHERE my_date LIKE '2016-05-%' 
ORDER BY my_date, my_sign + (my_sign =0) *2 DESC; 

が正しく表示されます:これは偶然に(今、私は週(または月)でグループにそれをしたいと思います

my_date  my_sign my_value cum_before cum_after 
2016-05-02  0 10000.00   0 10000.00 
2016-05-02  1 1860.00  10000 11860.00 
2016-05-02  -1 1860.00  11860 10000.00 
2016-05-03  1 1780.00  10000 11780.00 
2016-05-06  1 4625.00  11780 16405.00 
2016-05-09  1 14200.00  16405 30605.00 

、およびグループ内の行を処理する前に初期値に設定cum_beforeを持ちます前のグループのcum_afterにする必要があります)、グループ内の行を処理した後の累積値としてcum_afterを指定します。 以前の状態変数@cumがグループセットの最初の値で初期化されているように見えるものは複雑になります。

GROUPがORDER BY句に従わないように見えるので、正しい順序を維持するために一時テーブルを作成しています(DBに表示されている行を推測していると思います)。合計する:(=値@cum)グループ化する際に、SUM関数の内部で、それに応じて@cum変更すると、実際の合計に干渉しないように0を掛け、私は場所に割り当てる使用してい

CREATE TEMPORARY TABLE _t_ SELECT id FROM my_table 
ORDER BY my_date, my_sign + (my_sign =0) *2 DESC ; 

sign *値を返し、リセット条件が見つかると@cumを減算してvalueフィールドを追加します。

SELECT min(my_date) AS MinDate, max(my_date) AS MaxDate, 
@cum AS cum_before, SUM( 
    0 * (@cum := IF(my_sign !=0, my_sign * my_value, my_value)) + 
    IF(my_sign !=0, my_sign * my_value, - @cum + my_value) 
) AS cum_after 
FROM my_table as F, _t_, (SELECT @cum :=0) AS t 
WHERE _t_.id = F.id AND my_date LIKE '2016-05-%' 
GROUP BY date_format(my_date, "%y%U"); 

は以下を提供します:

MinDate  MaxDate  cum_before cum_after 
2016-05-02 2016-05-06   0 16405.00 
2016-05-09 2016-05-09  16405 30605.00 

は基本的にそれが表示されます

はの最初の行を@cum割り当てるには:私が得ることを期待することはあるので、間違っている

MinDate  MaxDate  cum_before cum_after 
2016-05-02 2016-05-06  10000 16405.00 
2016-05-09 2016-05-09  14200 14200.00 

以前の変数値を保持する代わりに、設定します。

可能な場合は、どのようにして正しいグループを取得できますか?

答えて

0

によってprevious answerを適用すると、各グループの後に累積変数がリセットされるため、1つのステップでは実行できないようです。 だから、可能な解決策は以下の通りです:

SELECT MinDate, MaxDate, @cum as cum_before, (@cum:[email protected]+tmp_cum) as cum_after 
FROM (SELECT min(my_date) AS MinDate, max(my_date) AS MaxDate, 
SUM( 
    0 * (@tmp := IF(my_sign !=0, my_sign * my_value, my_value)) + 
    IF(my_sign !=0, my_sign * my_value, - @tmp + my_value) 
) AS tmp_cum 
FROM my_table as F, _t_, (SELECT @tmp :=0) AS t 
WHERE _t_.id = F.id AND my_date LIKE '2016-05-%' 
GROUP BY date_format(my_date, "%y%U")) as SUBQ, (SELECT @cum:=0) as tmp_var; 

はパフォーマンスを知ってはいけない、またはこれを最適化することができます。