[英]SQL Server 2008 : How to update end date column for previous record
I have some records below. 我在下面有一些记录。 For each client, only one record can have END_DATE=12/31/9998
. 对于每个客户,只有一个记录可以具有END_DATE=12/31/9998
。
So I need to end date the previous record based on EFFECT_DATE
column. 因此,我需要根据EFFECT_DATE
列结束上EFFECT_DATE
记录的日期。
For example, I need to update the END_DATE
of ID=2
from 12/31/9998
to 7/17/2017
for CLT_NBR=12375
例如,我需要将CLT_NBR=12375
的ID=2
的END_DATE
从12/31/9998
到7/17/2017
ID CLT_NBR IS_PRIMARY EFFECT_DATE END_DATE
-----------------------------------------------
1 12375 1 8/13/2015 9/30/2015
2 12375 1 10/1/2015 12/31/9998
3 12375 1 7/18/2017 12/31/9998
4 12331 1 2/3/2016 7/8/2016
5 12331 1 7/9/2016 12/31/9998
You can use lead
to get the next effective date and subtract one day to update the current row's end date. 您可以使用lead
获取下一个生效日期,并减去一天以更新当前行的结束日期。
with cte as (select t.*,coalesce(dateadd(day,-1,lead(effect_date) over(partition by clt_nbr order by id),'9998-12-31') as new_end_date
from tbl t)
update cte
set end_date=new_end_date
For SQL Server 2008, use 对于SQL Server 2008,请使用
with rownums as (select t.*,row_number() over(partition by clt_nbr order by id) as rnum from tbl t)
,cte as (select r1.*,dateadd(day,-1,coalesce(r2.effect_date,'9999-01-01')) as new_end_date
from rownums r1
left join rownums r2 on r1.clt_nbr=r2.clt_nbr and r1.rnum=r2.rnum-1
)
update cte
set end_date=new_end_date
A solution based on joining and grouping related data. 基于对相关数据进行合并和分组的解决方案。 These days I often use CTE's, but before they were popular, one would have had to consider using something like this. 如今,我经常使用CTE,但在它们流行之前,人们不得不考虑使用类似的东西。
select *
into ##test1
from
(
select ID = 1, CLT_NBR = 12375, IS_PRIMARY = 1, EFFECT_DATE = cast('8/13/2015' as date), END_DATE = cast('9/30/2015' as date)
union all select ID = 2, CLT_NBR = 12375, IS_PRIMARY = 1, EFFECT_DATE = cast('10/1/2015' as date), END_DATE = cast('12/31/9998' as date)
union all select ID = 3, CLT_NBR = 12375, IS_PRIMARY = 1, EFFECT_DATE = cast('7/18/2017' as date), END_DATE = cast('12/31/9998' as date)
union all select ID = 4, CLT_NBR = 12331, IS_PRIMARY = 1, EFFECT_DATE = cast('2/3/2016' as date), END_DATE = cast('7/8/2016' as date)
union all select ID = 5, CLT_NBR = 12331, IS_PRIMARY = 1, EFFECT_DATE = cast('7/9/2016' as date), END_DATE = cast('12/31/9998' as date)
) x
select * from ##test1
select t.ID, t.CLT_NBR, t.IS_PRIMARY, t.EFFECT_DATE, END_DATE = isnull(dateadd(day,-1,min(t_next.EFFECT_DATE)),'9998-12-31')
from ##test1 t
left join ##test1 t_next on t_next.CLT_NBR = t.CLT_NBR and t_next.effect_date > t.effect_date
group by t.ID, t.CLT_NBR, t.IS_PRIMARY, t.EFFECT_DATE
update t
set END_DATE = helper.END_DATE
from ##test1 t
left join
(
select t.ID, t.CLT_NBR, t.IS_PRIMARY, t.EFFECT_DATE, END_DATE = isnull(dateadd(day,-1,min(t_next.EFFECT_DATE)),'9998-12-31')
from ##test1 t
left join ##test1 t_next on t_next.CLT_NBR = t.CLT_NBR and t_next.effect_date > t.effect_date
group by t.ID, t.CLT_NBR, t.IS_PRIMARY, t.EFFECT_DATE
) helper on helper.id = t.id
select * from ##test1
drop table ##test1
you can use query like below for a SQL 2008 compliant answer 您可以使用以下查询来获取符合SQL 2008的答案
CREATE TABLE yourTbl (ID int,CLT_NBR int,IS_PRIMARY int,EFFECT_DATE date, END_DATE date)
INSERT INTO yourTbl VALUES
(1 ,12375,1,'8/13/2015','9/30/2015')
,(2 ,12375,1,'10/1/2015','12/31/9998')
,(3 ,12375,1,'7/18/2017','12/31/9998')
,(4 ,12331,1, '2/3/2016','7/8/2016')
,(5 ,12331,1, '7/9/2016','12/31/9998')
;with y as
(
SELECT
*,
ROW_NUMBER() OVER(PARTITION BY CLT_NBR ORDER BY EFFECT_DATE DESC) R
FROM yourTbl WHERE END_DATE ='12/31/9998'
)
UPDATE y1
SET y1.END_DATE= y2.EFFECT_DATE
FROM
y y1 JOIN y y2
ON y1.R=y2.R+1 and y1.CLT_NBR=y2.CLT_NBR
select * from yourTbl
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.