我有一张表MyModel
,如下所示:
ID | Creation
---|-----------
1 | 2017-01-01
2 | NULL
3 | NULL
4 | 2017-01-09
5 | NULL
等等。
我需要为Creation
提供值NULL
,但是......
每行的Creation
需要大于其前一行。
所以以下查询对我不起作用
update MyModel
set Creation = getdate()
where Creation is null
因为它会破坏规则。
结果应该是
ID | Creation
---|-----------
1 | 2017-01-01
2 | 2017-01-02
3 | 2017-01-03
4 | 2017-01-09
5 | 2017-01-10
如果没有足够的日子在两个值之间有唯一日期怎么办?
如果Creation
为datetime
,则始终会插入有效的datetime
。记录之间的差异总是大于~30秒。
如果现有值不符合规定怎么办?
它们已经有序了。订单基于ID
。
答案 0 :(得分:1)
如果差距不超过从差距开始和结束的天数差异,这是一种方法。
declare @table table (ID int, Creation datetime)
insert into @table
values
(1,'2017-01-01'),
(2,NULL),
(3,NULL),
(4,'2017-01-09'),
(5,null),
(6,'2017-01-11'),
(7,null)
update t
set t.Creation = isnull(dateadd(day,(t2.id - t.ID) * -1,t2.creation),getdate())
from @table t
left join @table t2 on t2.ID > t.ID and t2.Creation is not null
where t.Creation is null
select * from @table
<强>返回强>
+----+-------------------------+
| ID | Creation |
+----+-------------------------+
| 1 | 2017-01-01 00:00:00.000 |
| 2 | 2017-01-07 00:00:00.000 |
| 3 | 2017-01-08 00:00:00.000 |
| 4 | 2017-01-09 00:00:00.000 |
| 5 | 2017-01-10 00:00:00.000 |
| 6 | 2017-01-11 00:00:00.000 |
| 7 | 2017-10-25 11:58:56.353 |
+----+-------------------------+
答案 1 :(得分:1)
使用common table expression row_number()
;with cte as (
select *
, rn = row_number() over (order by id)
from mymodel
)
update cte
set Creation = dateadd(day,cte.rn-x.rn,x.Creation)
from cte
cross apply (
select top 1 *
from cte i
where i.creation is not null
and i.id < cte.id
order by i.id desc
) x
where cte.creation is null;
select *
from mymodel;
rextester演示:http://rextester.com/WAA44339
返回:
+----+------------+
| id | Creation |
+----+------------+
| 1 | 2017-01-01 |
| 2 | 2017-01-02 |
| 3 | 2017-01-03 |
| 4 | 2017-01-09 |
| 5 | 2017-01-10 |
+----+------------+
答案 2 :(得分:-2)
你可以使用有用的光标,在那里你可以比较两个值并轻松更新值 尝试下面的事情
declare stageCursor cursor scroll for
select name, startdate, enddate from staging;
declare @name varchar(20),
@startdate datetime,
@enddate datetime;
open stageCursor
fetch next from stageCursor into @name, @startdate, @enddate
while @@fetch_status = 0 begin
update operations set o.enddate = dateadd(d, -1, s.startdate)
where name = @name --does this need to be restricted to just the latest operations row somehow?
insert operations (name, startdate, enddate)
values (@name, @startdate, @enddate);
fetch next from stageCursor into @name, @startdate, @enddate
end
close stageCursor
deallocate stageCursor
truncate table staging