I want to update 2 columns Enr
and Drop
based on StartDate
and EndDate
for a set of ID
values.
In attached screenshot, example for ID = 82
, we have 2 rows so have to compare 2 rows. Enddate (12/13/2013) in first row with startDate (2/17/2014) in next row and if datediff(dy, Startdate, Enddate) > 30
I have to update the columns Drop
in row1 to N and Enr
in row2 to Y accordingly.
Perform the same comparison for all matching id's in the group. I want to iterate over each set of ID values and compare start and end dates and based on that update columns err and Drop.
Please provide inputs on best way to write query for this? Any help is greatly appreciated.
Thanks Swetha
Try this by using CTE
and OUTER APPLY
combination as below:
DECLARE @table TABLE(id INT, StartDate DATE, EndDate DATE, Enr CHAR(1), [Drop] CHAR(1))
INSERT INTO @table VALUES
(82,'2010-12-14','2013-12-13','Y','N'),
(82,'2014-02-17','2016-12-21','N','Y'),
(125,'2010-12-22','2015-06-23','Y','N'),
(125,'2015-06-23','2015-06-30','N','N'),
(125,'2015-08-16',NULL,'N','N'),
(555,'2010-12-28','2017-03-31','Y','N'),
(555,'2017-03-31',NULL,'N','N')
;WITH cte AS(
SELECT t.*,
RANK() OVER(PARTITION BY id ORDER BY id, StartDate) rnk
FROM @table t
)
UPDATE ta SET ta.[Drop] = CASE WHEN t1.Diff>30 THEN 'Y' ELSE ta.[Drop] END,
ta.[Enr] = CASE WHEN t2.Diff>30 THEN 'Y' ELSE ta.[Enr] END
FROM cte t
INNER JOIN @table ta ON ta.id = t.id AND ta.StartDate = t.StartDate
OUTER APPLY(SELECT id, t1.StartDate, DATEDIFF(DAY,t.EndDate, t1.StartDate) Diff
FROM cte t1
WHERE t1.id = t.id
AND t1.rnk = t.rnk+1) t1
OUTER APPLY(SELECT id, t.StartDate, DATEDIFF(DAY,t2.EndDate, t.StartDate) Diff
FROM cte t2
WHERE t2.id = t.id
AND t2.rnk+1 = t.rnk) t2
OUTPUT:
id StartDate EndDate Enr Drop
82 2010-12-14 2013-12-13 Y Y
82 2014-02-17 2016-12-21 Y Y
125 2010-12-22 2015-06-23 Y N
125 2015-06-23 2015-06-30 N Y
125 2015-08-16 NULL Y N
555 2010-12-28 2017-03-31 Y N
555 2017-03-31 NULL N N
Note: Please confirm StartDate
for id 125 , that is different in Before and After update.
I hope it will resolve your problem
DECLARE @table TABLE(id INT, StartDate DATE, EndDate DATE, Enr CHAR(1), [Drop] CHAR(1))
INSERT INTO @table VALUES
(82,'2010-12-14','2013-12-13','Y','N'),
(82,'2014-02-17','2016-12-21','N','Y'),
(125,'2010-12-22','2015-06-23','Y','N'),
(125,'2015-06-23','2015-06-30','N','N'),
(125,'2015-08-16',NULL,'N','N'),
(555,'2010-12-28','2017-03-31','Y','N'),
(555,'2017-03-31',NULL,'N','N')
select * from @table
;WITH cte AS(
SELECT t.*,
RANK() OVER(PARTITION BY id ORDER BY id, StartDate) rnk,
lead(StartDate,1)OVER (PARTITION BY id ORDER BY id, StartDate) as NextStartDate,
Lag(enddate,1)OVER (PARTITION BY id ORDER BY id, StartDate) as PrevEndDate
FROM @table t
)
--select * from(
--select *,DATEDIFF(DD,PrevEndDate,StartDate) q,DATEDIFF(DD,EndDate,NextStartDate) r,
--case when (DATEDIFF(DD,PrevEndDate,StartDate) >30 and [Enr]='N') or [Enr]='Y' then 'Y' else 'N' end newEnr,
--case when (DATEDIFF(DD,EndDate,NextStartDate) >30 and [Drop]='N') or[Drop]='Y' then 'Y' else 'N' end newdrop
--from cte) as a
update t
set Enr=case when (DATEDIFF(DD,c.PrevEndDate,c.StartDate) >30 and c.[Enr]='N') or c.[Enr]='Y' then 'Y' else 'N' end,
t.[Drop]= case when (DATEDIFF(DD,c.EndDate,c.NextStartDate) >30 and c.[Drop]='N') or c.[Drop]='Y' then 'Y' else 'N' end
from @table t
inner join cte as c on t.id=c.id and t.StartDate=c.StartDate
select * from @table
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.