如何使用下一行检查当前行并更新当前行而不使用 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;
我强烈建议你不要使用 money
数据类型,而是使用 decimal
除了使用游标或 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;
我强烈建议你不要使用 money
数据类型,而是使用 decimal