简体   繁体   English

SQL 服务器:比较组中的行值并更新同一张表中的字段

[英]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.我想根据StartDateEndDate为一组ID值更新 2 列EnrDrop

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:尝试使用CTEOUTER 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 125StartDate ,这在更新之前和之后是不同的。

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM