繁体   English   中英

使用 T-SQL 根据先前行的值逐行更新表

[英]Using T-SQL to update a table row by row based on previous rows value

我有一个表,我正在尝试根据当前开始日期和前几行结束日期之间的日期差异创建一个 ID 字段

该表看起来像这样:

Table ID     |     Person ID    |     Start Date    |     End Date   
   1         |        1         |     01/01/2019    |    03/01/2019         
   2         |        1         |     03/01/2019    |    05/01/2019         
   3         |        1         |     07/01/2019    |    10/01/2019         
   4         |        1         |     10/01/2019    |    16/01/2019         
   4         |        1         |     16/01/2019    |    16/01/2019         
   5         |        1         |     18/01/2019    |    20/01/2019     

我想要它做的是将当前行的开始日期与前一行的结束日期进行比较,如果差值大于 1,那么我们希望将 New ID 字段增加 1。如果它小于 1,我们想要保持这个新字段与上一行相同(参见下面的示例)

Table ID     |     Person ID   |      Start Date    |     End Date     |  NEW ID Field
   1         |        1        |      01/01/2019    |    03/01/2019    |     1
   2         |        1        |      03/01/2019    |    05/01/2019    |     1
   3         |        1        |      06/01/2019    |    10/01/2019    |     2
   4         |        1        |      10/01/2019    |    16/01/2019    |     2
   4         |        1        |      16/01/2019    |    16/01/2019    |     2
   5         |        1        |      18/01/2019    |    20/01/2019    |     3

我目前必须这样做的代码一次更新整个表,而不是逐行更新,我想尽可能避免使用游标,因为这是一个相当大的表,并且会大大减慢我们的进程块。

我目前的代码是:

DECLARE @rown INT
DECLARE @MAX INT
DECLARE @Val INT
SET @rown = 1
SET @max = (select count(*) from dbo.table)
SET @Val = 1


WHILE @rown <> @max


Update dbo.table
  SET New_id_field = 
  (select Case WHEN LT_Flag = 0 then NULL
        WHEN 
        DateDiffFromPrev *-1 >1 
        THEN @Val + 1
        ELSE @Val
        END)

 FROM dbo.table t1
 INNER JOIN
 (
      SELECT 
      table_ID
      ,person_ID
      ,start_date
      ,end_date
      ,LT_Flag
      ,ROW_NUMBER() OVER (PARTITION BY person_id ORDER BY start_date) AS rownumber 
      ,DATEDIFF(day,  start_date, coalesce(lag(end_date) over (partition by Person_ID, LT_Flag order by start_date), start_date)) as DateDiffFromPrev  
FROM ) t2  
     ON t1.table_id = t2.table_id

SET @rown = @rown + 1

END 

对帖子中的任何格式表示歉意,因为我是堆栈溢出的新手! 提前谢谢了

WHILE是一个非常糟糕的解决方案。 使用分析 function LAG然后使用窗口聚合会好得多。 请注意,当差异为 1 天(根据我的评论)时,我不知道逻辑是什么,因此您必须更正:

WITH Prev AS(
    SELECT V.[Table ID],
           V.[Person ID],
           V.[Start Date],
           V.[End Date],
           LAG(V.[End Date],1,V.[End Date]) OVER (PARTITION BY V.[Person ID] ORDER BY V.[Start Date]) AS PrevEndDate --Not ordered on [Table ID] as it is not unique in the OP's data.
    FROM (VALUES(1,1,CONVERT(date,'01/01/2019',103),CONVERT(date,'03/01/2019',103)),         
                (2,1,CONVERT(date,'03/01/2019',103),CONVERT(date,'05/01/2019',103)),         
                (3,1,CONVERT(date,'07/01/2019',103),CONVERT(date,'10/01/2019',103)),         
                (4,1,CONVERT(date,'10/01/2019',103),CONVERT(date,'16/01/2019',103)),         
                (4,1,CONVERT(date,'16/01/2019',103),CONVERT(date,'16/01/2019',103)),         
                (5,1,CONVERT(date,'18/01/2019',103),CONVERT(date,'20/01/2019',103)))V([Table ID],[Person ID],[Start Date],[End Date]))
SELECT P.[Table ID],
       P.[Person ID],
       P.[Start Date],
       P.[End Date],
       SUM(CASE WHEN DATEDIFF(DAY,P.PrevEndDate,P.[Start Date]) < 1 THEN 0 
                WHEN DATEDIFF(DAY,P.PrevEndDate,P.[Start Date]) > 1 THEN 1
                --WHEN DATEDIFF(DAY,P.PrevEndDate,P.[Start Date]) = 1 THEN ???
           END) OVER (PARTITION BY P.[Person ID] ORDER BY P.[Start Date]
                      ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) +1 AS [New ID]
FROM Prev P;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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