如何使用 windows 函数写入 sql 当前行的值取决于前一行

How to use windows function to write sql where value of current row depends on previos row

我有 table 值

val1
1
2
3
4

我想跟随输出

1.00
2.50
4.25
6.12

table 中的每个值计算为 val1+0.5*val1(来自上一行) 所以对于.eg。 行 2 ---> 输出计算为 2+0.5*1.00= 2.50 行 3 ---> 输出计算为 3+0.5*2.50 = 4.25

当我使用以下 sql windows 函数时

SELECT *
   ,val1+SUM(0.50*val1) OVER (ORDER BY val1 ROWS between 1 PRECEDING and 1 PRECEDING) AS r
FROM #a1  

我得到输出

1.00
2.500
4.000
5.500

这可以通过递归 cte 来完成。

with rownums as (select val,row_number() over(order by val) as rnum 
                 from tbl)
/* This is the recursive cte */
,cte as (select val,rnum,cast(val as float) as new_val from rownums where rnum=1
         union all
         select r.val,r.rnum,r.val+0.5*c.new_val
         from cte c
         join rownums r on c.rnum=r.rnum-1
        )
/* End Recursive cte */
select val,new_val
from cte

Sample Demo

这称为指数平均。你可以用某种幂函数来做到这一点,比如说它被称为 power() (这可能因数据库而异)。

下面的方法可行 -- 但我不确定如果序列变长会发生什么。请注意,这有一个 id 列来指定顺序:

with t as (
      select 1 as id, 1 as val union all
      select 2, 2 union all select 3, 3 union all select 4, 4
     )
select t.*,
       ( sum(p_seqnum * val) over (order by id) ) / p_seqnum
from (select t.*,
             row_number() over (order by id desc) as seqnum,
             power(cast(0.5 as float), row_number() over (order by id desc)) as p_seqnum
      from t
     ) t;

这里是 rextester for Postgres. Here 是 SQL Fiddle 用于 SQL 服务器。

之所以有效,是因为指数平均是 "memory-less"。如果不是这样,您将需要一个递归 CTE,而这可能要贵得多。