跳过前 12 行后,如何根据前一行计算值?

5 sql-server-2005 sql-server-2008 sql-server

我正在寻求帮助来编写此查询。我在下面包含了一些示例数据。我最初的前提是从第 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
Run Code Online (Sandbox Code Playgroud)

并且通过dbo.IC_Raw_In在除 I_Date 之外的所有列上使用数据类型为 Money的大容量插入将数据导入到此表中。

然后当我运行这个查询时,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
Run Code Online (Sandbox Code Playgroud)

现在我想编写一个 SQL 查询来在名为C12WR 的新列中获取以下问题的结果。

我要排除(使用NULL),用于在第11行C12WR列和第12行中C12WR列“使用一个静态值,它是在AMPS12_C(在示出的表上面的结果值510.3958标记为粗体),该值每次我将数据导入我的表格时都会改变,所以每次都会动态改变。在AMPS12_C列中,它应该在第 13 行到表格末尾计算以下公式。

第13行之后,C12WR列=(C12WR的上一行的值(即当前行号-1)*11+I_C_O列的当前行值)/12

所以如果我计算它应该代表上面的公式如下。(我不想使用任何静态值,但对于这个公式的示例,我在这里采用静态值只是为了便于解释)

= ( 510.3958 * 11 + 510.2 ) / 12
Run Code Online (Sandbox Code Playgroud)

在我运行所需的查询后,我应该得到与此类似的输出:

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
Run Code Online (Sandbox Code Playgroud)

编辑: drachenstern ~ 我也合并了这两个问题。对于@BestBoy ~ 注意重新格式化。这应该可以帮助人们更快地理解事物。这让人们多帮助你一点。;)

jco*_*and 4

所以这不是一个很好的答案,这是其他人更好地接受和完善这个问题的一个起始答案。但我会尝试一下。

首先我有一个问题:您是否试图将其保留在视图中?我认为你不能做你想做的事情,这有点复杂,所以让我们检查一下你需要做的操作来真正做你想做的事情。

您表示希望前 12 行每次都是静态的,并且它们的最后一列应始终设置为 NULL,而其他行应保留其值。这就是我们需要用 SQL 进行编码的业务规则。但在我们将此作为规则进行编码之前,我们先问是否有一种方法可以确保这 12 行每次都是正确的行。如果我们可以做出这样的假设,那么我们就可以将其作为下一步的一部分。

您的下一个要求是对每一行与前一行进行计算。由于前 12 行是静态的(我认为没有计算),所以我们不必问“第一行怎么样”。因此,对前一行进行计算的最简单方法是为每一行分配一个 rownum,然后使用 rownum ID 进行比较。这与之前的要求相符。

因此,我们应该首先进行选择并分配 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
Run Code Online (Sandbox Code Playgroud)

但对于我执行此操作的方式,我会将这些值汇集到临时表中,然后使用它来计算出我需要的内容。这样您就可以在后续调用中引用这些列,如下所示:

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
Run Code Online (Sandbox Code Playgroud)

然后我们继续:

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
Run Code Online (Sandbox Code Playgroud)

使用此逻辑:在第 13 行之后,C12WR 列 = (prevrow.C12WR * 11 + currow.I_C_O 列) / 12

然后你只需从 temptable 返回你想要的值。

注意:我留下的东西。我没有定义临时表,也没有摆脱临时表。我没有使用适当的语法来进行临时寻址。我没有验证任何内容。我认为这将在存储过程中使用。我没有说明如何使用静态值作为存储过程传递的参数。

希望这可以帮助。希望其他人帮助使这个问题成为更好的答案;)

  • 可能可以作为视图来完成(您需要使用多个嵌套选择而不是针对临时表进行插入/更新),但会很慢且难以维护(*难以阅读*) (3认同)