[英]SQL Server : compare row values in a group and update a field in the same table
I want to update 2 columns Enr
and Drop
based on StartDate
and EndDate
for a set of ID
values.我想根据
StartDate
和EndDate
为一组ID
值更新 2 列Enr
和Drop
。
In attached screenshot, example for ID = 82
, we have 2 rows so have to compare 2 rows.在附加的屏幕截图中,例如
ID = 82
,我们有 2 行,因此必须比较 2 行。 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.第一行的结束日期(2013 年 12 月 13 日),下一行的
if datediff(dy, Startdate, Enddate) > 30
我必须将第 1 行中的列Drop
更新为第 2 行中的 N 和Enr
相应地传递给 Y。
Perform the same comparison for all matching id's in the group.对组中所有匹配的 id 执行相同的比较。 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.
我想遍历每组 ID 值并比较开始日期和结束日期,并基于该更新列 err 和 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:尝试使用
CTE
和OUTER APPLY
组合,如下所示:
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: 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.注意:请确认 id 125的
StartDate
,这在更新之前和之后是不同的。
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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.