2017-02-01 10 views
3

時刻ごとに1つの値がある時系列を仮定します。私は、現在の値+以前の値の合計を計算することによって、継続合計を計算しなければなりません。しかし、トリッキーな部分は、合計には上限があり、一定の値を超えないようにする必要があります。SQL上限、連続合計

例: 合計は+2でキャップされています。

+-----+---------+------------+ 
| row | measure | capped sum | 
+-----+---------+------------+ 
| 1 |  1 |   1 | 
| 2 |  3 |   2 | 
| 3 |  4 |   2 | 
| 4 |  -2 |   0 | 
| 5 |  1 |   1 | 
+-----+---------+------------+ 

行4の「キャップされた合計」は、前の行からの「キャップされた合計」「2」を使用して現在の値を加算して計算されます。結果は< 2なので、そのまま値を取ることができます。

問題は、HANAでは「キャップ付き合計」フィールドでLAG/Window関数を使用できません。それは私に "未知の列"エラーを与えるでしょう。

forループを使用せずにSQL/HANA SQLスクリプトでこれを解決する方法(これは非常に遅いでしょう)?

+0

ない、これはSUM OVERとMAX OVERを使用せずに行うことができることを確認。次の行に自己結合してそのように計算すると、SQLが連続して行をトラバースすると仮定することはできません。興味があれば、私は窓関数を使用するソリューションを持っています(しかし、LEADやLAGは使用しません)。 –

+0

常に可能なソリューションに興味があります。それが私のために働かない場合でも、他人を傷つけたり、助けたりしません。フィドルとして、あるいは解決策としてでもそれを落としてください。 – newBee

+0

hanaで再帰的なcteを使用できますか? –

答えて

1

このスクリプトは、まず実行中の合計の列を作成します。次に、その列を使用して、「超過」の列を作成します。実行中の合計が上限値を累積した値を累積します。次に、必要に応じて2より小さい値を与えるために、超過量を減算する。

DECLARE @capped_value INT = 2 
;WITH CTE AS 
(SELECT rowID,measure, 
    running_total = SUM(measure) OVER 
    (ORDER BY rowID ROWS UNBOUNDED PRECEDING) 
FROM dbo.test_capped_sum) 
, 
CTE2 AS 
(SELECT *, 
    overage_total = MAX(CTE.running_total) 
    OVER (ORDER BY rowID ROWS UNBOUNDED PRECEDING) - @capped_value 
FROM CTE) 

SELECT rowid,measure, 
    CASE WHEN CTE2.overage_total > 0 
    THEN CTE2.running_total- CTE2.overage_total 
    ELSE CTE2.running_total END 
    AS capped_sum FROM CTE2 
+0

私が使用できないCTEに依存しています。しかし、これは、CTEを使用できる他の人には役に立ちそうだと思います。 – newBee

+1

最初の行にキャップされた値より小さいメジャーがある場合に失敗する点を除いて、良い解決策です。そのために特別な条件を追加することができます。 –

+0

@newBee:CTEが再帰的でないかぎり、CTE2はネストした派生テーブルの構文バリエーションです。SELECT ... FROM(SELECT ... FROM(SELECT ... AS AS CTE)AS CTE2'とHanaはこれらをサポートします。 – dnoeth

1

この溶液を(OP通り)HANAでサポートされていない再帰CTEを使用します。それをサポートするデータベースで動作するソリューションを投稿する。

WITH ROWNUMS AS 
(SELECT T.*, 
     ROW_NUMBER() OVER(ORDER BY ROW) AS RNUM 
    FROM T) 
,RCTE AS 
(SELECT ROW, 
     RNUM, 
     MEASURE, 
     MEASURE AS CAPPED_SUM 
    FROM ROWNUMS 
    WHERE RNUM=1 
    UNION ALL 
    SELECT RN.ROW, 
      RN.RNUM, 
      RN.MEASURE, 
      CASE 
       WHEN R.CAPPED_SUM+RN.MEASURE>=2 THEN 2 
       ELSE R.CAPPED_SUM+RN.MEASURE 
      END 
    FROM ROWNUMS RN 
    JOIN RCTE R ON R.RNUM=RN.RNUM-1) 
SELECT ROW, 
     MEASURE, 
     CAPPED_SUM 
FROM RCTE 

Sample Demo

+0

ニースanswer tho。しかし私はforループを使うことができます。それに応じて私のソリューションを適応させます。この「アルゴリズム」はパラレル化できないため(計算は常に前の反復に依存します)、最終的には類似のパフォーマンスを達成します。 – newBee