TSQL:查找上一个'Day of The Week'逻辑的日期。是否有任何边缘情况会失败,是否可以简化?



我有各种SSIS作业,它们将在一周中的不同日子运行,并且需要参考前一个作业在运行之前是否已运行(通过日志表时间戳(。由于每种作业类型都有不同的时间表(取决于第三方集成需求(,我希望有一个通用的脚本来设置一些变量,这些变量可以根据需要在每个脚本中选择性地引用。

例如,"每隔一个星期三,‘作业A’运行一次,每隔一个周三,‘作业B’交错运行一次。如果‘作业A"在上周三没有运行(留下其运行的日志时间戳(,我就不需要运行‘作业B"。">

因此,我搜索了许多不同的方法,下面是我想到的:

-- Sets the first day of the week to Monday (used in finding 'previous day' below)
SET DATEFIRST 1
DECLARE
@DATE_TIME      SMALLDATETIME
,   @LastWeekMon    SMALLDATETIME
,   @LastWeekTue    SMALLDATETIME
,   @LastWeekWed    SMALLDATETIME
,   @LastWeekThu    SMALLDATETIME
,   @LastWeekFri    SMALLDATETIME
,   @LastWeekSat    SMALLDATETIME
,   @LastWeekSun    SMALLDATETIME
,   @PrevMon        SMALLDATETIME
,   @PrevTue        SMALLDATETIME
,   @PrevWed        SMALLDATETIME
,   @PrevThu        SMALLDATETIME
,   @PrevFri        SMALLDATETIME
,   @PrevSat        SMALLDATETIME
,   @PrevSun        SMALLDATETIME
,   @DontAllowPrevToBeToday BIT
,   @DAY_SPECIFIC_ADJUST INT
--SET CONSTANTS
--SET @DATE_TIME = GETDATE();
SET @DATE_TIME = '2018-07-21 00:00:00';
SET @DontAllowPrevToBeToday = 1; --true
select @DATE_TIME as DATE_TIME
-----------------------------------------
--GET LAST WEEK'S DAY-OF-THE-WEEK DATE (REGARDLESS OF SYSTEM ZERO DATE AND DATEFIRST SETTINGS)
SELECT @LastWeekMon = DATEADD(week,
DATEDIFF(week,'19000101',@DATE_TIME),'1899-12-25T00:00:00')  --12/25/1899 is a Monday
SELECT @LastWeekTue = DATEADD(week,
DATEDIFF(week,'19000101',@DATE_TIME),'1899-12-26T00:00:00')  --12/26/1899 is a Tuesday
SELECT @LastWeekWed = DATEADD(week,
DATEDIFF(week,'19000101',@DATE_TIME),'1899-12-27T00:00:00')  --12/27/1899 is a Wednesday
SELECT @LastWeekThu = DATEADD(week,
DATEDIFF(week,'19000101',@DATE_TIME),'1899-12-28T00:00:00')  --12/28/1899 is a Thursday
SELECT @LastWeekFri = DATEADD(week,
DATEDIFF(week,'19000101',@DATE_TIME),'1899-12-29T00:00:00')  --12/29/1899 is a Friday
SELECT @LastWeekSat = DATEADD(week,
DATEDIFF(week,'19000101',@DATE_TIME),'1899-12-30T00:00:00')  --12/30/1899 is a Saturday
SELECT @LastWeekSun = DATEADD(week,
DATEDIFF(week,'19000101',@DATE_TIME),'1899-12-31T00:00:00')  --12/31/1899 is a Sunday
SELECT @LastWeekMon as LastWeekMon, @LastWeekTue as LastWeekTue, @LastWeekWed as LastWeekWed, @LastWeekThu as LastWeekThu, @LastWeekFri as LastWeekFri, @LastWeekSat as LastWeekSat, @LastWeekSun as LastWeekSun
-----------------------------------------
SET @DAY_SPECIFIC_ADJUST = DATEDIFF(day, 0, @DATE_TIME) + -(0); --Mon + 0 = 1 = Monday
SELECT @PrevMon =
CASE
WHEN @DontAllowPrevToBeToday = 1 And DATEDIFF(day, 0, @DATE_TIME) = DATEADD(day, DATEDIFF(day, 0, @DATE_TIME - (@DAY_SPECIFIC_ADJUST) %7), 0) THEN
--PREV DAY IS TODAY, USE DAY FROM LAST WEEK
@LastWeekMon
ELSE
--PREV DAY SELECT
DATEADD(day, DATEDIFF(day, 0, @DATE_TIME - (@DAY_SPECIFIC_ADJUST) %7), 0)
END
SET @DAY_SPECIFIC_ADJUST = DATEDIFF(day, 0, @DATE_TIME) + -(1); --Mon + 1 = 2 = Tuesday
SELECT @PrevTue =
CASE
WHEN @DontAllowPrevToBeToday = 1 And DATEDIFF(day, 0, @DATE_TIME) = DATEADD(day, DATEDIFF(day, 0, @DATE_TIME - (@DAY_SPECIFIC_ADJUST) %7), 0) THEN
--PREV DAY IS TODAY, USE DAY FROM LAST WEEK
@LastWeekTue
ELSE
--PREV DAY SELECT
DATEADD(day, DATEDIFF(day, 0, @DATE_TIME - (@DAY_SPECIFIC_ADJUST) %7), 0)
END

SET @DAY_SPECIFIC_ADJUST = DATEDIFF(day, 0, @DATE_TIME) + -(2); --Mon + 2 = 3 = Wednesday
SELECT @PrevWed =
CASE
WHEN @DontAllowPrevToBeToday = 1 And DATEDIFF(day, 0, @DATE_TIME) = DATEADD(day, DATEDIFF(day, 0, @DATE_TIME - (@DAY_SPECIFIC_ADJUST) %7), 0) THEN
--PREV DAY IS TODAY, USE DAY FROM LAST WEEK
@LastWeekWed
ELSE
--PREV DAY SELECT
DATEADD(day, DATEDIFF(day, 0, @DATE_TIME - (@DAY_SPECIFIC_ADJUST) %7), 0)
END
SET @DAY_SPECIFIC_ADJUST = DATEDIFF(day, 0, @DATE_TIME) + -(3); --Mon + 3 = 4 = Thursday
SELECT @PrevThu =
CASE
WHEN @DontAllowPrevToBeToday = 1 And DATEDIFF(day, 0, @DATE_TIME) = DATEADD(day, DATEDIFF(day, 0, @DATE_TIME - (@DAY_SPECIFIC_ADJUST) %7), 0) THEN
--PREV DAY IS TODAY, USE DAY FROM LAST WEEK
@LastWeekThu
ELSE
--PREV DAY SELECT
DATEADD(day, DATEDIFF(day, 0, @DATE_TIME - (@DAY_SPECIFIC_ADJUST) %7), 0)
END
SET @DAY_SPECIFIC_ADJUST = DATEDIFF(day, 0, @DATE_TIME) + -(4); --Mon + 4 = 5 = Friday
SELECT @PrevFri =
CASE
WHEN @DontAllowPrevToBeToday = 1 And DATEDIFF(day, 0, @DATE_TIME) = DATEADD(day, DATEDIFF(day, 0, @DATE_TIME - (@DAY_SPECIFIC_ADJUST) %7), 0) THEN
--PREV DAY IS TODAY, USE DAY FROM LAST WEEK
@LastWeekFri
ELSE
--PREV DAY SELECT
DATEADD(day, DATEDIFF(day, 0, @DATE_TIME - (@DAY_SPECIFIC_ADJUST) %7), 0)
END
SET @DAY_SPECIFIC_ADJUST = DATEDIFF(day, 0, @DATE_TIME) + -(5); --Mon + 5 = 6 = Saturday
SELECT @PrevSat =
CASE
WHEN @DontAllowPrevToBeToday = 1 And DATEDIFF(day, 0, @DATE_TIME) = DATEADD(day, DATEDIFF(day, 0, @DATE_TIME - (@DAY_SPECIFIC_ADJUST) %7), 0) THEN
--PREV DAY IS TODAY, USE DAY FROM LAST WEEK
@LastWeekSat
ELSE
--PREV DAY SELECT
DATEADD(day, DATEDIFF(day, 0, @DATE_TIME - (@DAY_SPECIFIC_ADJUST) %7), 0)
END
SET @DAY_SPECIFIC_ADJUST = DATEDIFF(day, 0, @DATE_TIME) + -(6); --Mon + 6 = 7 = Sunday
SELECT @PrevSun =
CASE
WHEN @DontAllowPrevToBeToday = 1 And DATEDIFF(day, 0, @DATE_TIME) = DATEADD(day, DATEDIFF(day, 0, @DATE_TIME - (@DAY_SPECIFIC_ADJUST) %7), 0) THEN
--PREV DAY IS TODAY, USE DAY FROM LAST WEEK
@LastWeekSun
ELSE
--PREV DAY SELECT
DATEADD(day, DATEDIFF(day, 0, @DATE_TIME - (@DAY_SPECIFIC_ADJUST) %7), 0)
END
SELECT @PrevMon as PrevMon, @PrevTue as PrevTue, @PrevWed as PrevWed, @PrevThu as PrevThu, @PrevFri as PrevFri, @PrevSat as PrevSat, @PrevSun as PrevSun

这听起来合理吗?有没有更简单的方法来实现这一点?我肯定会有的,但我被难住了。

感谢您的帮助和反馈!

免责声明这本质上是一条长评论,但由于涉及大量代码和评论,因此作为回答发布。

来自@deeg的《如何在SQL中获取上次运行的作业详细信息》。

SELECT  t2.instance_id
,t1.name as JobName
,t2.step_id as StepID
,t2.step_name as StepName
,CONVERT(CHAR(10), CAST(STR(t2.run_date,8, 0) AS DATETIME), 111) as RunDate
,STUFF(STUFF(RIGHT('000000' + CAST ( t2.run_time AS VARCHAR(6 ) ) ,6),5,0,':'),3,0,':') as RunTime
,t2.run_duration
,CASE t2.run_status WHEN 0 THEN 'Failed'
WHEN 1 THEN 'Succeeded' 
WHEN 2 THEN 'Retry' 
WHEN 3 THEN 'Cancelled' 
WHEN 4 THEN 'In Progress' 
END as ExecutionStatus
,t2.message as MessageGenerated    
FROM    msdb.dbo.sysjobs t1
JOIN    msdb.dbo.sysjobhistory t2
ON t1.job_id = t2.job_id   
--Join to pull most recent job activity per job, not job step
JOIN    (
SELECT  TOP 1
t1.job_id
,t1.start_execution_date
,t1.stop_execution_date
FROM    msdb.dbo.sysjobactivity t1
--If no job_id detected, return last run job
ORDER 
BY      last_executed_step_date DESC
) t3
--Filter on the most recent job_id
ON t1.job_id = t3.job_Id
--Filter out job steps that do not fall between start_execution_date and stop_execution_date
AND CONVERT(DATETIME, CONVERT(CHAR(8), t2.run_date, 112) + ' ' 
+ STUFF(STUFF(RIGHT('000000' + CONVERT(VARCHAR(8), t2.run_time), 6), 5, 0, ':'), 3, 0, ':'), 121)  
BETWEEN t3.start_execution_date AND t3.stop_execution_date

将为您提供在开始执行日期和停止执行日期之间运行的所有作业(根据需要进行更改(。如果作业A在RunDate(和/或RunTime(之间的日期差异在七天内成功。然后运行作业B

也就是。。。其中t2.JobName = 'yourjob't2.run_status = 1,然后运行作业B。

这种逻辑有帮助吗?请注意,如果需要,您可以过滤掉返回的内容,以摆脱单独的步骤。

相关内容

最新更新