如何使用windows函数编写sql,其中当前行的值取决于previos行

时间:2018-02-12 20:10:13

标签: sql sql-server window-functions

我有值的表

val1
1
2
3
4

我希望关注输出

1.00
2.50
4.25
6.12

表中的每个值都计算为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

2 个答案:

答案 0 :(得分:3)

这可以使用递归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

答案 1 :(得分:3)

这称为指数平均。您可以使用某种幂函数来执行此操作,例如它被称为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;

这是Postgres的rextesterHere是SQL Server的SQL小提琴。

这是有效的,因为指数平均是“无记忆”。如果不是这样,你需要一个递归的CTE,这可能会更加昂贵。