我想做的是我有两个日期,并使用DateDiff
来获取两个日期之间的差值。例如,我已经计划了Start Date
和actual start Date
,而我得到的这个日期之间的差是5
,现在我想把这一天添加到Finish date
中。
如果我的Finish date
不是我想的,而是我想的,那么我想补充一下这个差值,并想找到下一个finish date
,因为我们在下一个即将到来的日期后面。
Sum (DATEDIFF(day, sa.PlannedStartDate, sa.ActualStartDate)) OVER
(Partition
By ts.Id)as TotalVariance,
Case when (Sum (DATEDIFF(day, sa.PlannedStartDate, sa.ActualStartDate))
OVER
(Partition By ts.Id) >30) then 'Positive' end as Violation,
DATEADD (day, DATEDIFF(day, sa.PlannedStartDate, sa.ActualStartDate))as
Summar violations,
如果活动 1 -planned Start date
是8/21/2019
,但是actual start date
是9/21/2019
,那么在这种情况下,我们落后了30天。 / p>
现在下一个活动将被延迟,因此我想将此差异添加到下一个活动中。
如果第二项活动planned Start date
是08/25/2019
,但是由于活动1的延迟,start date
将更改为第二项活动,在这种情况下,我想查找该新日期。
Activity PlannedStartdate ActualStartDate Variance NewPlannedstartdate
Activity 1 8/21/2019 9/21/2019 30
Acivity 2 8/26/2019 null 9/26/2019
答案 0 :(得分:1)
以下是您可以在SSMS中运行的示例:
-- CREATE ACTIVITY TABLE AND ADD SOME DATA --
DECLARE @Activity TABLE ( ActivityId INT, PlannedStart DATE, ActualStart DATE );
INSERT INTO @Activity (
ActivityId, PlannedStart, ActualStart
)
VALUES
( 1, '08/21/2019', '08/27/2019' ), ( 1, '08/26/2019', NULL ), ( 1, '09/14/2019', NULL );
查询@Activity以查看其中的内容:
SELECT * FROM @Activity ORDER BY ActivityId, PlannedStart;
@活动内容:
+------------+--------------+-------------+
| ActivityId | PlannedStart | ActualStart |
+------------+--------------+-------------+
| 1 | 2019-08-21 | 2019-08-27 |
| 1 | 2019-08-26 | NULL |
| 1 | 2019-09-14 | NULL |
+------------+--------------+-------------+
查询@Activity以考虑新的开始日期:
;WITH Activity_CTE AS (
SELECT
ROW_NUMBER() OVER ( ORDER BY PlannedStart ) AS Id,
ActivityId, PlannedStart, ActualStart, DATEDIFF( dd, PlannedStart, ActualStart ) Delayed
FROM @Activity
WHERE
ActivityId = @ActivityId
)
SELECT
ActivityId,
PlannedStart,
ActualStart,
DATEADD( dd, Delays.DaysDelayed, PlannedStart ) AS NewStart
FROM Activity_CTE AS Activity
OUTER APPLY (
SELECT CASE
WHEN ( Delayed IS NOT NULL ) THEN Delayed
ELSE ISNULL( ( SELECT TOP 1 Delayed FROM Activity_CTE WHERE Id < Activity.Id AND Delayed IS NOT NULL ORDER BY Id DESC ), 0 )
END AS DaysDelayed
) AS Delays
ORDER BY
PlannedStart;
返回
+------------+--------------+-------------+------------+
| ActivityId | PlannedStart | ActualStart | NewStart |
+------------+--------------+-------------+------------+
| 1 | 2019-08-21 | 2019-08-27 | 2019-08-27 |
| 1 | 2019-08-26 | NULL | 2019-09-01 |
| 1 | 2019-09-14 | NULL | 2019-09-20 |
+------------+--------------+-------------+------------+
这里真正的“魔术”是这一行:
ELSE ISNULL( ( SELECT TOP 1 Delayed FROM Activity_CTE WHERE Id < Activity.Id AND Delayed IS NOT NULL ORDER BY Id DESC ), 0 )
它正在检查自身是否有延迟的任何先前记录。如果未找到,则返回0。然后使用此值将日期添加到 PlannedStart 日期,以确定 NewStart 日期。 ORDER BY也特别值得注意。按DESC顺序排序可确保我们在当前行之前获得“最近”延迟。
以这种方式使用CTE还考虑了可能不会在第一条记录上发生延迟的想法(例如,说计划的08/26已延迟而不是08/21)。它方便地为我们提供了一个子表,可在我们的外部应用程序中进行查询。
如果您将CTE的SELECT中的所有列都包括在内,就会看到以下内容:
+----+------------+--------------+-------------+---------+-------------+
| Id | ActivityId | PlannedStart | ActualStart | Delayed | DaysDelayed |
+----+------------+--------------+-------------+---------+-------------+
| 1 | 1 | 2019-08-21 | 2019-08-27 | 6 | 6 |
| 2 | 1 | 2019-08-26 | NULL | NULL | 6 |
| 3 | 1 | 2019-09-14 | NULL | NULL | 6 |
+----+------------+--------------+-------------+---------+-------------+
因为第一个记录是唯一一个延迟的记录,所以它的6天延迟在以下每个记录中一直存在。