4

SQLクエリで前の行から計算された値を参照するにはどうすればよいですか? 私の場合、各行は、前の行と同じ値を何らかの形で操作するイベントです。

生データは次のようになります。

イベント番号 イベントタイプ 合計料金
3 ACQ 32
2 OUT ヌル
1 OUT ヌル

各 Eventtype=OUT が、Remaincharge という列の前の行の totalcharge の半分であるとします。

Eventno Eventtype Totalcharge Remaincharge
3 ACQ 32 32
2 OUT NULL 16
1 OUT NULL 8

すでに LAG 分析関数を試しましたが、前の行から計算値を取得できません。次のようなことを試しました:

LAG(remaincharge, 1, totalcharge) OVER (PARTITION BY ...) as remaincharge

しかし、remaingcharge が見つからなかったため、これは機能しませんでした。

これを達成する方法はありますか?累積合計を取得できる分析関数が必要ですが、代わりに前の値にアクセスできる関数が必要です。

前もって感謝します!

問題の説明を更新する

私の例の問題は一般的なものだったと思いますが、ここに問題のより良い説明があります:

合計料金の残りは、outqty/(前の残りの数量) の比率によって決まります。

Eventno Eventtype Totalcharge Remainqty Outqty
4 ACQ 32 100 0
3 その他のヌル 100 0
2 OUT NULL 60 40
1 OUT NULL 0 60
Eventno Eventtype Totalcharge Remainqty Outqty Remaincharge
4 ACQ 32 100 0 32
3 OTHER NULL 100 0 32 - (0/100 * 32) = 32
2 OUT NULL 60 40 32 - (40/100 * 32) = 12.8
1 OUT NULL 0 60 12.8 - (60/60 * 12.8) = 0
4

3 に答える 3

4

あなたの場合、 FIRST_VALUE()分析関数を使用して最初の値を計算し、サブクエリでRANK()で除算する必要がある 2 の累乗を計算して、それを使用できます。これはあなたの例に非常に固有のものですが、一般的なアイデアを提供する必要があります:

select eventno, eventtype, totalcharge
     , case when eventtype <> 'OUT' then firstcharge
            else firstcharge / power(2, "rank" - 1) 
       end as remaincharge
  from ( select a.*
              , first_value(totalcharge) over 
                  ( partition by 1 order by eventno desc ) as firstcharge
              , rank() over ( partition by 1 order by eventno desc ) as "rank"
           from the_table a
                )

デモ用のSQL Fiddleを次に示します。生データにパーティション化するものが何もないため、私は何もパーティション化していません...

于 2013-04-22T09:45:25.227 に答える
2

更新された要件を処理しているように見える、ウィンドウ句を使用するための Ben の回答のバリエーション:

select eventno, eventtype, totalcharge, remainingqty, outqty,
    initial_charge - case when running_outqty = 0 then 0
    else (running_outqty / 100) * initial_charge end as remainingcharge
from (
    select eventno, eventtype, totalcharge, remainingqty, outqty,
        first_value(totalcharge) over (partition by null
            order by eventno desc) as initial_charge,
        sum(outqty) over (partition by null
            order by eventno desc
            rows between unbounded preceding and current row)
            as running_outqty
    from t42
);

19.23行目の代わりに与えることを除いて、それは12.8あなたの式がそれであるべきであることを示唆しています:

   EVENTNO EVENT TOTALCHARGE REMAININGQTY     OUTQTY REMAININGCHARGE
---------- ----- ----------- ------------ ---------- ---------------
         4 ACQ            32          100          0              32
         3 OTHER                      100          0              32
         2 OUT                         60         40            19.2
         1 OUT                          0         60               0

別のスプリットを追加して、2 つのステップで 60 から 0 になるようにすると、ミックス内に別の非 OUT レコードも含まれます。

   EVENTNO EVENT TOTALCHARGE REMAININGQTY     OUTQTY REMAININGCHARGE
---------- ----- ----------- ------------ ---------- ---------------
         6 ACQ            32          100          0              32
         5 OTHER                      100          0              32
         4 OUT                         60         40            19.2
         3 OUT                         30         30             9.6
         2 OTHER                       30          0             9.6
         1 OUT                          0         30               0

残りの数量は一貫しており、以前に行ったものの現在の合計を効果的に追跡できるという前提がありますが、あなたが示したデータからはそれがもっともらしく見えます. 内側のクエリが各行の現在の合計を計算し、外側のクエリが計算を行います。凝縮される可能性がありますが、このように明確になることを願っています...

于 2013-04-22T12:23:12.850 に答える
1

ベンの答えはより良いものです(おそらくパフォーマンスが向上します)が、次のようにすることもできます:

select t.*, (connect_by_root Totalcharge) / power (2,level-1) Remaincharge
from the_table t
start with EVENTTYPE = 'ACQ'
connect by prior eventno = eventno + 1;

読みやすいと思います

ここにデモがあります

于 2013-04-22T10:14:20.690 に答える