如何使用 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
这称为指数平均。你可以用某种幂函数来做到这一点,比如说它被称为 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,而这可能要贵得多。
我有 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
这称为指数平均。你可以用某种幂函数来做到这一点,比如说它被称为 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,而这可能要贵得多。