【问题标题】:Updating every row in a table with IF Statement conditions使用 IF 语句条件更新表中的每一行
【发布时间】:2011-03-30 10:09:03
【问题描述】:

这个让我卡住了。

数据:

Month           Total         Impact    Forecast
------------------------------------------------
2010-04-01    45792.0000    1.0000    NULL
2010-05-01    51789.0000    1.0000    NULL
2010-06-01    58228.0000    1.0000    NULL
2010-07-01    52956.5217    1.0000    NULL
2010-08-01    53600.4700    0.8810    NULL
2010-09-01    54257.8784    1.1838    NULL
2010-10-01    55134.0669    1.0000    NULL 

现在我要做的是遍历表的当前内容并使用条件 IF 语句更新预测列,如下所示:

If Impact = 1.0000 then forecast = (current month) total * Impact
If Impact < 1.0000 then forecast = (month -1) total * Impact
If Impact > 1.0000 then forecast = (month -2) total * Impact

我确实考虑过使用 CASE 语句,虽然使用以前的日期计算预测让我感到困惑,我想我需要使用 while 语句和 RBAR。

非常感谢。

【问题讨论】:

    标签: sql tsql if-statement while-loop sql-update


    【解决方案1】:

    这个怎么样:

    UPDATE [Table]
    SET
        [Forecast] = [Impact] * CASE
            WHEN [Impact] = 1.0000 THEN
            (
                SELECT
                    [InnerTable].[Total]
                FROM [Table] AS [InnerTable]
                WHERE [InnerTable].[Month] = [Table].[Month]
            )
            WHEN [Impact] < 1.0000 THEN
            (
                SELECT
                    [InnerTable].[Total]
                FROM [Table] AS [InnerTable]
                WHERE [InnerTable].[Month] = DATEADD(month, -1, [Table].[Month])
            )
            ELSE
            (
                SELECT
                    [InnerTable].[Total]
                FROM [Table] AS [InnerTable]
                WHERE [InnerTable].[Month] = DATEADD(month, -2, [Table].[Month])
            )
        END    
    FROM [Table]
    

    【讨论】:

    • 对于月份为 2010-08-01、2010-09-01 和 2010-10-01 的行生成错误的结果
    • @Daniel:我认为SET [Forecast] = CASE 应该是SET [Forecast] = [Impact] * CASE。 (假设使用的影响应该始终是当月的影响,无论应该使用哪一个月的总数。)
    • 那么如何将预测设置为 = Impact * CASE?
    • @Mark/@Lee: 是的,那是个错误,现在解决了; @KM:这也解决了结果吗?
    • @Daniel Renshaw,很可能它会解决问题,但你的版本仍然没有我的效率高(使用 set showplan_all on)
    【解决方案2】:

    试试这个:

    DECLARE @YourTable table (MonthOf datetime, TotalOf numeric(9,4), Impact numeric(9,4), forecast numeric(9,4))
    
    INSERT @YourTable VALUES('2010-04-01',    45792.0000,    1.0000,    NULL)
    INSERT @YourTable VALUES('2010-05-01',    51789.0000,    1.0000,    NULL)
    INSERT @YourTable VALUES('2010-06-01',    58228.0000,    1.0000,    NULL)
    INSERT @YourTable VALUES('2010-07-01',    52956.5217,    1.0000,    NULL)
    INSERT @YourTable VALUES('2010-08-01',    53600.4700,    0.8810,    NULL)
    INSERT @YourTable VALUES('2010-09-01',    54257.8784,    1.1838,    NULL)
    INSERT @YourTable VALUES('2010-10-01',    55134.0669,    1.0000,    NULL)
    
    ;WITH MonthValues AS
    (
        SELECT
            DATEADD(month,DATEDIFF(month,0,MonthOf),0) AS MonthYear
                ,SUM(TotalOf) TotalOf
        FROM @YourTable
        GROUP BY DATEADD(month,DATEDIFF(month,0,MonthOf),0)
    )
    UPDATE y
        SET Forecast=CASE
                         WHEN Impact = 1.0000 then m1.TotalOf * Impact
                         WHEN Impact < 1.0000 then m2.TotalOf * Impact
                         WHEN Impact > 1.0000 then m3.TotalOf * Impact
                     END
        FROM @YourTable                     y
            LEFT OUTER JOIN MonthValues  m1 ON DATEADD(month,DATEDIFF(month,0,y.MonthOf),0)=m1.MonthYear
            LEFT OUTER JOIN MonthValues  m2 ON DATEADD(month,-1,DATEADD(month,DATEDIFF(month,0,y.MonthOf),0))=m2.MonthYear
            LEFT OUTER JOIN MonthValues  m3 ON DATEADD(month,-2,DATEADD(month,DATEDIFF(month,0,y.MonthOf),0))=m3.MonthYear
    
    SELECT * FROM @YourTable
    

    输出:

    MonthOf                 TotalOf     Impact  forecast
    ----------------------- ----------- ------- -----------
    2010-04-01 00:00:00.000 45792.0000  1.0000  45792.0000
    2010-05-01 00:00:00.000 51789.0000  1.0000  51789.0000
    2010-06-01 00:00:00.000 58228.0000  1.0000  58228.0000
    2010-07-01 00:00:00.000 52956.5217  1.0000  52956.5217
    2010-08-01 00:00:00.000 53600.4700  0.8810  46654.6956
    2010-09-01 00:00:00.000 54257.8784  1.1838  62689.9304
    2010-10-01 00:00:00.000 55134.0669  1.0000  55134.0669
    
    (7 row(s) affected)
    

    【讨论】:

      【解决方案3】:

      你可以做一个花哨的组合语句,但我只使用 3 个单独的更新语句:

      UPDATE table
      SET forecast = (current month) total * Impact
      WHERE Impact = 1.0000
      GO
      UPDATE table
      SET forecast = (month -1) total * Impact 
      WHERE Impact < 1.0000
      GO
      UPDATE table
      SET forecast = (month -2) total * Impact 
      WHERE Impact > 1.0000
      GO
      

      【讨论】:

      • 关键字'current'附近的语法不正确; 'total' 附近的语法不正确。 'total' 附近的语法不正确。
      • 对不起,那部分是伪代码,直接从问题中复制而来。我以为您只是担心 IF 的语法,但我现在可以看到您必须从其他行中提取值,这要困难得多。
      猜你喜欢
      • 1970-01-01
      • 2021-08-03
      • 1970-01-01
      • 2017-04-25
      • 1970-01-01
      • 2015-03-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多