根据条件用上一行的值更新列
Update a column with the value from previous row based on conditions
我有一个 table,我需要在其中找到满足几个条件的值,如果满足这些条件,我需要为每一列分配相同的值
Table
ID Name Salary rownum
1 Jon 500 1
1 Jim 600 2
1 Jack 700 3
1 Bob 1000 4
2 Adam 500 1
2 Aron 600 2
2 James 900 3
2 Jay 1000 4
第一个条件是我需要有相同的ID,然后在ID内我需要比较第一行和第二行如果差异小于或等于100。我只能比较Rownum 1和2和 2 与 3 等等。确定条件是否满足后,我需要将薪水值更新为 Rownum 1 的值,直到满足条件并保持名称相同为止。
预期输出
Table
ID Name Salary rownum
1 Jon 500 1
1 Jim 500 2
1 Jack 500 3
1 Bob 1000 4
2 Adam 500 1
2 Aron 500 2
2 James 900 3
2 Jay 900 4
Jim 的薪水为 600,与 Jon 的薪水的差值 <=100,而 Jack 的薪水为 700,与 Jim 的差值 <=100,因为 Jim 在 Jon 的薪水范围内,而 Jack 在 Jim 的薪水范围内,这些值是连续的,所以我们需要 Jon 对这些行的值,而 Bob 是独立的,因为它不在范围内。同样的逻辑适用于 ID = 2
试试这个:
如果
“left join self
+ where Salary + 100 * (jointable.rownum - rownum) = jointable.Salary
的数据不为空”然后更新 Salary
update T
set Salary = NewSalary
from (
select T2.*,T1.Salary NewSalary,(T2.rownum - T1.rownum) fd
from [Table] T1
left join [Table] T2 on T1.ID = T2.ID
and T1.rownum <> T2.rownum
and (T2.rownum - T1.rownum) > 0
and T1.[Salary] + 100 * (T2.rownum - T1.rownum) = T2.[Salary]
where T2.id is not null
) T ;
| ID | Name | Salary | rownum |
|----|-------|--------|--------|
| 1 | Jon | 500 | 1 |
| 1 | Jim | 500 | 2 |
| 1 | Jack | 500 | 3 |
| 1 | Bob | 1000 | 4 |
| 2 | Adam | 500 | 1 |
| 2 | Aron | 500 | 2 |
| 2 | James | 900 | 3 |
| 2 | Jay | 900 | 4 |
您的问题并不像看起来那么简单,因为与当前行(例如 750)相比,前一行的值(例如 800)可能更大。
也有可能有更多的岛和间隙而不是一个。
以下是我的解决方案。另见 working demo
; with cte as
(
select *
, toUpdate= case
when
salary - lag( salary) over( partition by Id order by rownum asc) between 0 and 100
then
1
else
0
end
from t
)
update t5
set t5.salary=t4.newsalary
from t t5
join
(
select
t1.*,
rn=row_number () over( partition by t1.id, t1.rownum order by t3.rownum desc),
newsalary=t3.salary
from cte t1
outer apply
(
select *
from cte t2
where t2.id=t1.id
and t2.rownum<t1.rownum
and t2.toUpdate=0
) t3
)t4
on t4.rn=1 and t4.toUpdate=1 and t5.id=t4.id and t5.rownum=t4.rownum
select * from t
我有一个 table,我需要在其中找到满足几个条件的值,如果满足这些条件,我需要为每一列分配相同的值
Table
ID Name Salary rownum
1 Jon 500 1
1 Jim 600 2
1 Jack 700 3
1 Bob 1000 4
2 Adam 500 1
2 Aron 600 2
2 James 900 3
2 Jay 1000 4
第一个条件是我需要有相同的ID,然后在ID内我需要比较第一行和第二行如果差异小于或等于100。我只能比较Rownum 1和2和 2 与 3 等等。确定条件是否满足后,我需要将薪水值更新为 Rownum 1 的值,直到满足条件并保持名称相同为止。
预期输出
Table
ID Name Salary rownum
1 Jon 500 1
1 Jim 500 2
1 Jack 500 3
1 Bob 1000 4
2 Adam 500 1
2 Aron 500 2
2 James 900 3
2 Jay 900 4
Jim 的薪水为 600,与 Jon 的薪水的差值 <=100,而 Jack 的薪水为 700,与 Jim 的差值 <=100,因为 Jim 在 Jon 的薪水范围内,而 Jack 在 Jim 的薪水范围内,这些值是连续的,所以我们需要 Jon 对这些行的值,而 Bob 是独立的,因为它不在范围内。同样的逻辑适用于 ID = 2
试试这个:
如果
“left join self
+ where Salary + 100 * (jointable.rownum - rownum) = jointable.Salary
的数据不为空”然后更新 Salary
update T
set Salary = NewSalary
from (
select T2.*,T1.Salary NewSalary,(T2.rownum - T1.rownum) fd
from [Table] T1
left join [Table] T2 on T1.ID = T2.ID
and T1.rownum <> T2.rownum
and (T2.rownum - T1.rownum) > 0
and T1.[Salary] + 100 * (T2.rownum - T1.rownum) = T2.[Salary]
where T2.id is not null
) T ;
| ID | Name | Salary | rownum |
|----|-------|--------|--------|
| 1 | Jon | 500 | 1 |
| 1 | Jim | 500 | 2 |
| 1 | Jack | 500 | 3 |
| 1 | Bob | 1000 | 4 |
| 2 | Adam | 500 | 1 |
| 2 | Aron | 500 | 2 |
| 2 | James | 900 | 3 |
| 2 | Jay | 900 | 4 |
您的问题并不像看起来那么简单,因为与当前行(例如 750)相比,前一行的值(例如 800)可能更大。 也有可能有更多的岛和间隙而不是一个。
以下是我的解决方案。另见 working demo
; with cte as
(
select *
, toUpdate= case
when
salary - lag( salary) over( partition by Id order by rownum asc) between 0 and 100
then
1
else
0
end
from t
)
update t5
set t5.salary=t4.newsalary
from t t5
join
(
select
t1.*,
rn=row_number () over( partition by t1.id, t1.rownum order by t3.rownum desc),
newsalary=t3.salary
from cte t1
outer apply
(
select *
from cte t2
where t2.id=t1.id
and t2.rownum<t1.rownum
and t2.toUpdate=0
) t3
)t4
on t4.rn=1 and t4.toUpdate=1 and t5.id=t4.id and t5.rownum=t4.rownum
select * from t