【问题标题】:T-SQL sequential updating with two columns具有两列的 T-SQL 顺序更新
【发布时间】:2020-09-14 12:16:24
【问题描述】:

我有一个由以下人员创建的表:

CREATE TABLE table1 
(
    id INT,
    multiplier INT,
    col1 DECIMAL(10,5)
)

INSERT INTO table1 
VALUES (1, 2, 1.53), (2, 3, NULL), (3, 2, NULL),
       (4, 2, NULL), (5, 3, NULL), (6, 1, NULL)

结果:

id  multiplier  col1
-----------------------
1   2           1.53000
2   3           NULL
3   2           NULL
4   2           NULL
5   3           NULL
6   1           NULL

我想添加一列col2,它被定义为multiplier * col1,但是col1 的下一个值随后更新为采用先前计算的col2 值。

结果表应如下所示:

id  multiplier  col1        col2
---------------------------------------
1       2         1.53000     3.06000
2       3         3.06000     9.18000
3       2         9.18000    18.36000
4       2        18.36000    36.72000
5       3        36.72000   110.16000
6       1       110.16000   110.16000

这可能使用 T-SQL 吗?我尝试了一些不同的方法,例如将id 加入id - 1,并使用UPDATE 进行顺序更新并设置变量,但我无法让它工作。

【问题讨论】:

    标签: sql sql-server sql-update window-functions recursive-query


    【解决方案1】:

    递归 CTE 可能是最好的方法。假设您的ids 没有间隙:

    with cte as (
          select id, multiplier, convert(float, col1) as col1, convert(float, col1 * multiplier) as col2
          from table1
          where id = 1
          union all
          select t1.id, t1.multiplier, cte.col2 as col1, cte.col2 * t1.multiplier
          from cte join
               table1 t1
               on t1.id = cte.id + 1
         )
    select *
    from cte;
    

    Here 是一个 dbfiddle。

    请注意,我将目标类型转换为float,这对这种操作很方便。如果您愿意,可以转换回decimal

    【讨论】:

      【解决方案2】:

      基本上,这需要一个聚合/窗口函数来计算列值的乘积。但是 SQL 中不存在这样的 set 函数。我们可以用算术来解决这个问题:

      select
          id,
          multiplier,
          coalesce(min(col1) over() * exp(sum(log(multiplier)) over(order by id rows between unbounded preceding and 1 preceding)), col1) col1,
          min(col1) over() * exp(sum(log(multiplier)) over(order by id)) col2
      from table1
      

      Demo on DB Fiddle

      编号 |乘数 | col1 | col2 -: | ---------: | -----: | -----: 1 | 2 | 1.53 | 3.06 2 | 3 | 3.06 | 9.18 3 | 2 | 9.18 | 18.36 4 | 2 | 18.36 | 36.72 5 | 3 | 36.72 | 110.16 6 | 1 | 110.16 | 110.16

      如果有否定的multipliers,这将失败。

      如果您想要update 声明:

      with cte as (
          select col1, col2,
              coalesce(min(col1) over() * exp(sum(log(multiplier)) over(order by id rows between unbounded preceding and 1 preceding)), col1) col1_new,
              min(col1) over() * exp(sum(log(multiplier)) over(order by id)) col2_new
          from table1
      )
      update cte set col1 = col1_new, col2 = col2_new
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-12-15
        • 2014-05-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多