web-dev-qa-db-ja.com

最初の12行をスキップした後、前の行に基づいて値を計算するにはどうすればよいですか?

このクエリを作成するためのヘルプを探しています。以下にいくつかのサンプルデータを含めました。私の最初の前提は、13行目以降のすべての値が動的で、最初の12行が静的な値になることです。各行の値を計算する数式を知っています。

以下は私の見解のDDLです

CREATE VIEW [v_AMP_C] AS

    SELECT     in.I_Date  ,--Date
               in.I_O_P   ,--Money
               in.I_O_H   ,--Money
               in.I_O_L   ,--Money
               in.I_C_O   ,--Money 
               c.AMPS12_C  --Money
    FROM       dbo.IC_Raw_In in
    INNER JOIN dbo.AMPS12_C c ON in.I_Serial = c.i_serial

i_Dateを除くすべての列でデータタイプがMoneyの一括挿入dbo.IC_Raw_Inを使用して、データがこのテーブルにインポートされます。

次に、このクエリを実行するとSELECT * FROM v_AMP_Cが出力として以下のようになりました

I_Date   I_O_P     I_O_H    I_O_L    I_C_O     AMPS12_C
01/10/11 509.75    515      508      512.45    512.45
01/10/11 511.7     511.7    506.1499 506.5499  509.4999
01/10/11 507.1499  510.25   507.1499 510.25    509.7499
01/10/11 510       512.3499 509.2999 512.3499  510.3999
01/10/11 512.5     512.5    511.1499 512       510.7199
01/10/11 512.25    512.5    510.1    510.95    510.7583
01/10/11 510.5499  511.7999 510      511.7999  510.9071
01/10/11 511.1     511.85   508.1499 508.8999  510.6562
01/10/11 508.8999  510      508.5    509.95    510.5777
01/10/11 509.8999  509.8999 508.5    508.85    510.4049
01/10/11 509.5     511.2    509      510.5     510.4136
01/10/11 510.5     511.7999 510.1    510.2   **510.3958**
01/10/11 510.2999  511.35   510.25   510.75    510.2541
01/10/11 510.35    512      510.35   510.95    510.6208
01/10/11 510.95    511.7999 510.6    511.1     510.6916
01/10/11 511.0499  511.35   509.1    509.1     510.4208
01/10/11 509.5     509.5    508.1    508.5     510.1291
01/10/11 508.45    508.95   507      507       509.7999
01/10/11 507       508.2    503.2999 503.2999  509.0916
01/10/11 504       505      503.5    504.6499  508.7374
01/10/11 505.45    506.35   504      504.7     508.2999
01/10/11 504.7     505.5    504.2    505.5     508.0208
01/10/11 505.35    505.7    503.1    503.6499  507.4499
01/10/11 504.5     504.5    499.5499 500.5     506.6416
01/10/11 500.45    502      500.25   501       505.8291
01/10/11 501       501.2999 499.5499 500.3999  504.9499
01/10/11 500.45    500.7999 498.6499 498.6499  503.9124
01/10/11 498.7     499.25   498.0499 498.35    503.0166
01/10/11 498.75    499.95   498.7    499       502.2249
01/10/11 499.25    499.6499 498.6499 499.45    501.5957
01/10/11 499.2999  501.1499 499.1    500.8999  501.3957
01/10/11 501.1     502.5    500.5499 502.5     501.2166
01/10/11 502.35    502.95   501      501.5     500.9499
01/10/11 501.5     501.5    500      500.5     500.5333
01/10/11 500       501.35   499.5    499.7999  500.2124
01/10/11 499.95    500.3999 499.2999 500.2999  500.1957
01/10/11 500       501.3999 499.5    499.6499  500.0832
01/10/11 499.7999  501.25   499.6499 500.0499  500.0541

ここで、SQLクエリを記述して、以下のクエリに対してC12WRという新しい列で結果を取得します。

C12WR列の最初の11行を除外(NULLを使用)し、C12WR列の12行目を "静的値を使用するはAMPS12_Cにあります(上記の表の結果では、値は510.3958太字としてマークされています)。この値は、データをテーブルにインポートするたびに変化するため、毎回動的に変化します。そして、AMPS12_C列では、13行目からテーブルの最後までの以下の式を計算する必要があります。

13行目以降、C12WR列=(C12WR * 11からの上記の行の値(つまり、行番号-1)+ I_C_O列からの現在の行の値)/ 12

したがって、計算すると、上記の式は次のようになります。 (私は静的な値を使用したくありませんが、この数式の例では、説明を簡単にするためにここでは静的な値を使用しています)

= ( 510.3958 * 11 + 510.2 ) / 12

そして、目的のクエリを実行すると、次のような出力が得られます。

I_Date   I_O_P       I_O_H       I_O_L       I_C_O       AMPS12_C    C12WR
01/10/11 509.75      515         508         512.4500122 512.45      NULL
01/10/11 511.7000122 511.7000122 506.1499939 506.5499878 509.4999    NULL
01/10/11 507.1499939 510.25      507.1499939 510.25      509.7499    NULL
01/10/11 510         512.3499756 509.2999878 512.3499756 510.3999    NULL
01/10/11 512.5       512.5       511.1499939 512         510.7199    NULL
01/10/11 512.25      512.5       510.1000061 510.9500122 510.7583    NULL
01/10/11 510.5499878 511.7999878 510         511.7999878 510.9071    NULL
01/10/11 511.1000061 511.8500061 508.1499939 508.8999939 510.6562    NULL
01/10/11 508.8999939 510         508.5       509.9500122 510.5777    NULL
01/10/11 509.8999939 509.8999939 508.5       508.8500061 510.4049    NULL
01/10/11 509.5       511.2000122 509         510.5       510.4136    NULL
01/10/11 510.5       511.7999878 510.1000061 510.2000122 510.3958333 510.3958333
01/10/11 510.2999878 511.3500061 510.25      510.75      510.2541657 510.3795149
01/10/11 510.3500061 512         510.3500061 510.9500122 510.6208344 510.4103887
01/10/11 510.9500122 511.7999878 510.6000061 511.1000061 510.6916682 510.4553573
01/10/11 511.0499878 511.3500061 509.1000061 509.1000061 510.4208374 510.509078
01/10/11 509.5       509.5       508.1000061 508.5       510.1291707 510.3916554
01/10/11 508.4500122 508.9500122 507         507         509.8000031 510.2340174
01/10/11 507         508.2000122 503.2999878 503.2999878 509.0916697 509.964516
01/10/11 504         505         503.5       504.6499939 508.7375031 509.4091386
01/10/11 505.4500122 506.3500061 504         504.7000122 508.3000031 509.0125432
01/10/11 504.7000122 505.5       504.2000122 505.5       508.0208359 508.6531656
01/10/11 505.3500061 505.7000122 503.1000061 503.6499939 507.450002  508.3904018
01/10/11 504.5       504.5       499.5499878 500.5       506.6416677 507.9953678
01/10/11 500.4500122 502         500.25      501         505.8291677 507.3707539
01/10/11 501         501.2999878 499.5499878 500.3999939 504.9499995 506.8398577
01/10/11 500.4500122 500.7999878 498.6499939 498.6499939 503.9124985 506.3032024
01/10/11 498.7000122 499.25      498.0499878 498.3500061 503.0166651 505.665435
01/10/11 498.75      499.9500122 498.7000122 499         502.2249985 505.0558159
01/10/11 499.25      499.6499939 498.6499939 499.4500122 501.5958328 504.5511646
01/10/11 499.2999878 501.1499939 499.1000061 500.8999939 501.3958333 504.1260686
01/10/11 501.1000061 502.5       500.5499878 502.5       501.2166672 503.857229
01/10/11 502.3500061 502.9500122 501         501.5       500.9499995 503.7441266
01/10/11 501.5       501.5       500         500.5       500.5333328 503.557116
01/10/11 500         501.3500061 499.5       499.7999878 500.212499  503.3023564
01/10/11 499.9500122 500.3999939 499.2999878 500.2999878 500.1958313 503.0104923
01/10/11 500         501.3999939 499.5       499.6499939 500.0833308 502.784617
01/10/11 499.7999878 501.25      499.6499939 500.0499878 500.0541636 502.5233984

編集者: drachenstern〜2つの質問もマージしました。 @BestBoyの場合〜再フォーマットに注意してください。これは人々が少し早く物事を理解するのに役立つはずです。これにより、人々はもう少し手助けをしたいようになります。 ;)

5
user1234

これは良い答えではありません。これは、他の誰かがこれを引き受けてこれをより良く洗練するための最初の答えのようなものです。しかし、私はそれを突き刺します。

最初に私は質問があります:これをビューに保持しようとしていますか?あなたがやりたいことのためにあなたができるとは思わない、それはちょっと複雑なので、あなたがする操作を調べてみましょうあなたが実際にしたいことをするために行う必要があります。

最初の12行は毎回静的であり、最後の列は常にNULLに設定され、他の行はその値を保持する必要があると述べました。これがSQLでエンコードする必要があるビジネスルールです。ただし、これを原則としてエンコードする前に、これらの12行が毎回RIGHT行であることを確認する方法があるかどうかを確認しましょう。その仮定ができれば、次のステップの一部としてこれを行うことができます。

次の要件は、前の行を使用して各行で計算を行うことです。最初の12行は静的である(そして私は計算されていないと思います)ので、「最初の行はどうですか」と尋ねる必要はありません。したがって、前の行で計算を行う最も簡単な方法は、各行に行番号を割り当て、比較で行番号IDを使用することです。これは前の要件と一致します。

したがって、次のように、selectを実行し、rownumも割り当てることから始めます。

SELECT     
    ROW_NUMBER() OVER (ORDER BY in.I_Date) AS rownum,
    in.I_Date  ,--Date
    in.I_O_P   ,--Money
    in.I_O_H   ,--Money
    in.I_O_L   ,--Money
    in.I_C_O   ,--Money 
    c.AMPS12_C  --Money
    CAST(0.0 AS Money) AS C12WR
FROM
    dbo.IC_Raw_In in
INNER JOIN 
    dbo.AMPS12_C c ON in.I_Serial = c.i_serial

しかし、これを行う方法では、これらの値を一時テーブルに流し込み、それを使用して必要なものを計算します。そうすれば、次のように、後続の呼び出しで列を参照できます。

UPDATE t 
SET C12WR = NULL
FROM temptable t
WHERE t.rownum < 12 -- see how we set the values = null here?

UPDATE t 
SET C12WR = 510.3958
FROM temptable t
WHERE t.rownum = 12 -- see how we set the value to something static? 
                    -- If this were a stored procedure we could use a value passed in here

そして次に続けます:

UPDATE t 
SET C12WR = ( ( t2.C12WR * 11.0 ) + t.I_C_O ) / 12.0
FROM temptable t
INNER JOIN temptable t2 ON t.rownum = (t2.rownum - 1) -- this let's us get the previous row
WHERE t.rownum > 12

このロジックを使用:13行目以降、C12WR列=(prevrow.C12WR * 11 + currow.I_C_O列)/ 12

そして、あなたは単にあなたが望むものからあなたが望む値を返します。

通知:私がやめたこと。一時テーブルを定義していません。一時テーブルを削除していません。誘惑的なアドレス指定に適切な構文を使用しませんでした。何も検証しませんでした。これはストアード・プロシージャーで使用される予定だったと思います。静的な値をストアドプロシージャの受け渡しパラメーターとして使用する方法は説明しませんでした。

お役に立てれば。他の誰かがこれをより良い答えにするのを助けてくれることを願っています;)

4
jcolebrand