具有两列的T-SQL顺序更新

具有两列的T-SQL顺序更新,sql,sql-server,sql-update,window-functions,recursive-query,Sql,Sql Server,Sql Update,Window Functions,Recursive Query,我有一个由以下人员创建的表: 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 ---------

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

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
和设置变量的顺序更新,但我无法让它工作。

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

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;
他是一把小提琴


请注意,我将目标类型转换为
float
,这便于此类操作。如果愿意,可以将其转换回十进制。

基本上,这需要一个聚合/窗口函数来计算列值的乘积。但是,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

id | multiplier | 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
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