如何根据具有共享ID的其他行更新SQL行?

时间:2017-08-24 16:59:29

标签: sql-server

目前,我的表格如下所示:

ID|Date    |Val         
1 |1/1/2016|1           
2 |1/1/2016|0    
3 |1/1/2016|0  
1 |2/1/2016|0  
2 |2/1/2016|1   
3 |2/1/2016|1   
1 |3/1/2016|0  
2 |3/1/2016|0   
3 |3/1/2016|0

我想更新它,以便值继承每个ID,但不会在早期日期比值首次出现时更新。此外,该值只能更改为0到1,反之则不然。所以最终产品看起来像:

ID|Date    |Val         
1 |1/1/2016|1           
2 |1/1/2016|0    
3 |1/1/2016|0  
1 |2/1/2016|1  
2 |2/1/2016|1   
3 |2/1/2016|1   
1 |3/1/2016|1  
2 |3/1/2016|1   
3 |3/1/2016|1

我尝试了几个代码组合,但是在值首次出现的日期之后携带值的条件是让我沮丧。我很感激任何帮助!

1 个答案:

答案 0 :(得分:1)

在SQL Server 2012+中,使用汇总max()作为窗口函数over()(在common table expression内部以简化update):

;with cte as (
select *
  , MaxVal = max(convert(int,val)) over (partition by id order by date)
from t
)
update cte
  set val = maxVal
where val <> maxVal

rextester演示:http://rextester.com/ZPGWB94088

结果:

+----+------------+-----+
| id |    Date    | Val |
+----+------------+-----+
|  1 | 2016-01-01 |   1 |
|  2 | 2016-01-01 |   0 |
|  3 | 2016-01-01 |   0 |
|  1 | 2016-02-01 |   1 |
|  2 | 2016-02-01 |   1 |
|  3 | 2016-02-01 |   1 |
|  1 | 2016-03-01 |   1 |
|  2 | 2016-03-01 |   1 |
|  3 | 2016-03-01 |   1 |
+----+------------+-----+

在SQL Server 2012之前,您可以使用以下内容:

update t
  set Val = 1
from t
  inner join (
    select i.Id, min(i.Date) as Date
    from t as i
    where i.Val = 1
    group by i.Id
  ) as m
    on t.Id = m.Id
   and t.Date >= m.Date
   and t.Val = 0

rextester演示:http://rextester.com/RLEAO15622