while循环-SQL Logic

时间:2018-07-31 18:15:38

标签: sql sql-server-2008 while-loop

输入

 date        |  username |    program | workflow  | Pending_Audits  |Audits_Carry_Forward

 31-07-2018  |  ram      |   Pre pay  | Sisi      |      -1         |      -12 
 27-07-2018  |  ram      |   Pre pay  | Sisi      |      -111       |       0
 25-07-2018  |  ram      |   Pre pay  | Sisi      |      -16        |     -14

我有上表,我正在写一段时间条件,以从给定日期更新Audits_Carry_Forward列。

逻辑是将给定日期的audits_carry_forward更新为与给定日期具有相同程序和工作流程的下一行“ pending_audits”列

所需的输出:

 date        |  username |    program | workflow  | Pending_Audits  |Audits_Carry_Forward

 31-07-2018  |  ram      |   Pre pay  | Sisi      |      -1         |      -111 
 27-07-2018  |  ram      |   Pre pay  | Sisi      |      -111       |      -16
 25-07-2018  |  ram      |   Pre pay  | Sisi      |      -16        |      -14

所以在这种情况下,我想将“ 25-07-2018”的Pending_audits数据更新为给定日期以上的audits_carry_forward。

我尝试过的sql逻辑

DECLARE @date DATE = '2018-07-25' 
DECLARE @username VARCHAR(100)= 'ram' 
DECLARE @program VARCHAR(100)= 'Pre pay' 
DECLARE @workflow VARCHAR(100)= 'Sisi' 
DECLARE @a INT 

WHILE ( @date <= Cast(Getdate() AS DATE) ) 
  BEGIN 
      SET @a = (SELECT Count(*) 
                FROM   dbo.homehealthpp1 
                WHERE  username = @username 
                       AND program = @program 
                       AND workflow = @workflow 
                       AND date = @date) 

      IF ( @a = 1 ) 
        BEGIN 
            UPDATE dbo.homehealthpp1 
            SET    audits_carry_forward = (SELECT pending_audits 
                                           FROM   dbo.homehealthpp1 
                                           WHERE  username = @username 
                                                  AND program = @program 
                                                  AND workflow = @workflow 
                                                  AND date = @date) 
            WHERE  username = @username 
                   AND program = @program 
                   AND workflow = @workflow 
                   AND date = Cast(Dateadd(d, 1, @date) AS DATE) 
        END 

      SET @date = Cast(Dateadd(d, 1, @date) AS DATE) 
  END 

当日期顺序显示时,上述情况适用。但不适用于上述日期不连续的情况。

1 个答案:

答案 0 :(得分:0)

假设username/workflow/program是通用值,则可以执行此操作。

我们在row_number()上添加了一个username/workflow/program分区,然后可以从下面的(audits_carry_forward)行中为匹配的username/workflow/program更新rn值集(-1),但仅当行(rn)不为1时。

DECLARE @Test TABLE ([date] DATE, username VARCHAR(100), program VARCHAR(10), workflow VARCHAR(10), pending_audits INT, audits_carry_forward INT)

INSERT INTO @Test
VALUES ('2018-07-31','ram','Pre pay','Sisi',-1,-12),
       ('2018-07-27','ram','Pre pay','Sisi',-111,0),
       ('2018-07-25','ram','Pre pay','Sisi',-16,-14)

;WITH x AS
(
    SELECT *, ROW_NUMBER() OVER(PARTITION BY username,program,workflow ORDER BY [date]) AS RN
    FROM @Test
)

UPDATE T1 SET audits_carry_forward = (SELECT pending_audits FROM X T2 WHERE T1.username=T2.username AND T1.program=T2.program AND T1.workflow=T2.workflow AND T2.RN=T1.RN-1)
FROM X T1
WHERE T1.RN!=1

SELECT *
FROM @Test
ORDER BY [date] DESC

值得注意的是,在SQL中不建议使用循环/游标。这称为RBAR(行排成一列)方法,比基于集的方法要昂贵得多,而所有数据都是同时更新的。您会发现,随着时间和经验的发展,大多数(尽管不是全部)事情都可以在不使用循环/光标的情况下完成。