如何使用下一行检查当前行并更新当前行而不使用 while 循环和游标

How to check the current row with next row and update the current row not using while loop and cursor

除了使用游标或 while 循环检查当前行与下一行并更新当前行并遍历数据集中的所有行之外,还有其他方法吗?

例如,这是 table 我们有:

id  date                      value
1   2020-09-01 00:00:00.000   0.00
2   2020-09-01 00:15:00.000   0.30
3   2020-09-01 00:30:00.000   0.00
4   2020-09-01 00:45:00.000   0.15
5   2020-09-01 01:00:00.000   0.20
6   2020-09-01 01:15:00.000   0.10
7   2020-09-01 01:30:00.000   0.10
8   2020-09-01 01:45:00.000   0.00
9   2020-09-01 02:00:00.000   0.00



declare @i int = 1, @new_value money = 0.3

while @i <= 10
begin

        select @new_value = iif(value> (@new_value * 0.2) and value < @new_value,
                                       value,
                                       @new_value)
        from table
        where value >= 0.1
        and id = @i + 1;

    set @i = @i + 1
end

select @new_value -- Output will be 0.10

这个 while 循环遍历每一行并根据某些条件更新@new_value,然后检查下一行。

我想看看有没有什么方法可以不使用循环或游标而得到相同的结果。

这里是递归cte

declare @tbl table
(
    id  int,
    [value] decimal(5,2)
)

insert into @tbl values
(1, 0.00),
(2, 0.30),
(3, 0.00),
(4, 0.15),
(5, 0.20),
(6, 0.10),
(7, 0.10),
(8, 0.00),
(9, 0.00);

declare @new_value decimal(5,2) = 0.3;

with rcte as
(
    select  id, value, 
            new_value = iif(value > (@new_value * 0.2) 
                        and value < @new_value,
                        value,
                        new_value)
    from    @tbl
    where   id  = 1

    union all

    select  t.id, t.value, 
            new_value = iif(t.value > (r.new_value * 0.2) 
                        and t.value < r.new_value,
                        t.value,
                        r.new_value)
    from    rcte r
            inner join @tbl t   on  r.id    = t.id - 1
)
select  *
from    rcte

您可以为此使用 LAG window 函数以及 MIN 聚合

SELECT MIN(t.value)
FROM (
    SELECT *,
        LAG(t.value, 1, 0.3) OVER (ORDER BY t.id) AS prevValue
    FROM [table] AS t
) AS t
WHERE t.value > (t.prevValue * 0.2) AND value < prevValue;

SQL Fiddle


我强烈建议你不要使用 money 数据类型,而是使用 decimal