我正在尝试更新SQL报告sproc的WHERE子句,以检查给定日期是在下一次出现的类之前还是之前。课程有一个StartDate,每周在同一天发生一次。鉴于StartDate,我如何找到一周中那一天的下一次出现?
E.G。如果StartDate是2012年1月18日,星期三,我运行截至今天,2012年1月26日的报告,我需要找到2/1/2012,即1/26之后的下一个星期三。如果StartDate是1/19,周四,我今天运行报告,公式应该给我今天的周四1/26。
这是SQL中的一种想法:
SELECT *
FROM tbl_Class cs
INNER JOIN tbl_Enrollment sce ON cs.pk_ClassID = sce.fk_ClassID
WHERE ...
AND sce.StartDate < [Find date of next class after @AsOfDate using cs.StartDate]
答案 0 :(得分:1)
这是我提出的一些示例SQL。 3次迭代,这样你就可以了解我的结果。第3次迭代应该是您可以通过将列名替换为变量而合并到WHERE子句中。
设定:
DECLARE @Startdate DATETIME,@currentdate datetime
SET @Startdate = '1-26-2012'
SET @Currentdate = '1-23-2012'
--This section just normalizes it so you can use 7 as the interval
--The offset depends on your current setting for DATEFIRST, U.S. English default is 7, Sunday.
-- see http://msdn.microsoft.com/en-us/library/ms187766.aspx
DECLARE @StartDateWorkingDayOfWeek int,@CurrentDateWorkingDayOfWeek int
SELECT @StartDateWorkingDayOfWeek =(DATEPART(weekday,@Startdate)-2)
SELECT @CurrentDateWorkingDayOfWeek=(DATEPART(weekday,@Currentdate)-2)
迭代#1
--Iteration 1
IF @StartDateWorkingDayOfWeek < @CurrentDateWorkingDayOfWeek
SELECT DATEADD(DAY,DATEDIFF(DAY,0,@Currentdate)/7*7 + 7,@StartDateWorkingDayOfWeek)
else
SELECT DATEADD(DAY,DATEDIFF(DAY,0,@Currentdate)/7*7 + 0,@StartDateWorkingDayOfWeek)
迭代#2
--Iteration 2
SELECT DATEADD(DAY,DATEDIFF(DAY,0,@Currentdate)/7*7 +
CASE WHEN @StartDateWorkingDayOfWeek < @CurrentDateWorkingDayOfWeek
then 7
ELSE 0
end
,@StartDateWorkingDayOfWeek)
迭代#3
--iteration 3
SELECT DATEADD(DAY,DATEDIFF(DAY,0,@Currentdate)/7*7 +
CASE WHEN (DATEPART(weekday,@Startdate)-2) < (DATEPART(weekday,@Currentdate)-2)
then 7
ELSE 0
end
,(DATEPART(weekday,@Startdate)-2))
给本文提示: http://www.sqlmag.com/article/tsql3/datetime-calculations-part-3
答案 1 :(得分:0)
感谢TetonSig及其对此链接的引用,我想出了这些内容:http://www.sqlmag.com/article/tsql3/datetime-calculations-part-3
我们可以将上一个星期一的日期排除在当前日期之前(@AsOfDate),如下所示:
SELECT DATEADD(day, DATEDIFF(day,0, @AsOfDate-1) /7*7, 0);
这将获得1/1/1900和@AsOfDate之间的天数天数。 / 7 * 7将其转换为整周,然后将其添加回到1/1/1900(星期一)以获得@AsOfDate之前的星期一。 -1使其不包含@AsOfDate。没有减1,如果@AsOfDate在星期一,它将被计为“前一个”星期一。
接下来作者表示,为了在下周一获得包容性,我们只需要将7添加到上一个星期一的独家公式:
SELECT DATEADD(d, DATEDIFF(day,0, @AsOfDate-1) /7*7, 0)+7;
瞧!我们现在已经在@AsOfDate之后的第一个星期一了。唯一的问题是,上面的星期一(0)在我的情况下是一个移动的目标。我需要按课程日期确定的第一个[DayOfWeek],而不是第一个星期一。我需要换掉上面0的ClassDayOfWeek计算:
DATEADD(d, DATEDIFF(d, [ClassDayOfWeek], @AsOfDate-1)/7*7, [ClassDayOfWeek])+7
我想计算ClassDayOfWeek而不依赖或不得不设置@@ datefirst。所以我相对于基准日计算了它:
DATEDIFF(d, 0, StartDate)%7
这为Mon提供0,为Sun提供6,因此我们现在可以将其插入[ClassDayOfWeek]。我应该指出,这个0-6的值是以1/1 / 1900-1 / 7/1900表示为int的日期。
DATEADD(d, DATEDIFF(d, DATEDIFF(d, 0, StartDate)%7, @AsOfDate-1)/7*7, DATEDIFF(d, 0, StartDate)%7)+7
根据问题使用:
SELECT *
FROM tbl_Class cs
INNER JOIN tbl_Enrollment sce ON cs.pk_ClassID = sce.fk_ClassID
WHERE ...
AND sce.StartDate < DATEADD(d,
DATEDIFF(d,
DATEDIFF(d, 0, cs.StartDate)%7,
@AsOfDate-1)/7*7,
DATEDIFF(d, 0, cs.StartDate)%7)+7
答案 2 :(得分:0)
我用一个简单的案例陈述得出了答案 在你的情况下,@ targetDOW将是班级的一周。
DECLARE @todayDOW INT = DATEPART(dw, GETDATE());
DECLARE @diff INT = (@targetDOW - @todayDOW);
SELECT
CASE
WHEN @diff = 0 THEN GETDATE()
WHEN @diff > 0 THEN DATEADD(d,@diff,GETDATE())
WHEN @diff < 0 THEN DATEADD(d,@diff + 7,GETDATE())
END;