根据条件用上一行的值更新列

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 |

SQL Fiddle DEMO LINK

您的问题并不像看起来那么简单,因为与当前行(例如 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