我正在使用一些较旧的代码库,在许多地方都找不到简洁性。
我们在数据库中不断使用的一段代码是确定两个日期是否在同一个程序年内。例如,2011年计划年度从2011年7月1日开始,到2012年7月1日结束(或技术上是前一天)
通常我认为解决这个问题的方法是使用这种代码:
if Month(@EnrollmentDate)>=7 begin
set @StartDate='07/01/'+LTRIM(RTRIM(Year(@EnrollmentDate)))
set @EndDate='07/01/'+LTRIM(RTRIM(Year(@EnrollmentDate)+1))
end else begin
set @StartDate='07/01/'+LTRIM(RTRIM(Year(@EnrollmentDate)-1))
set @EndDate='07/01/'+LTRIM(RTRIM(Year(@EnrollmentDate)))
end
...
where (ENROLLMENTDATE >= @StartDate and ENROLLMENTDATE < @EndDate)
我最近碰巧要解决这个问题,而且我头脑中突然出现的东西更简洁:
where year(dateadd(mm,-6,ENROLLMENTDATE)) = year(dateadd(mm,-6,@EnrollmentDate))'
在我将新错误引入“正常工作”的系统之前,我想问一下这个问题。这两段代码完全相同吗?他们总是给出相同的输出(假设有效日期)吗?
答案 0 :(得分:1)
我看到的问题是,根据优化器,你的解决方案(看起来更好)可能不会使用ENROLLMENTDATE上定义的索引,因为你正在对它进行操作,而原始的解决方案会。如果该字段上没有索引,那么我没有看到问题
答案 1 :(得分:1)
处理这种情况的一种更简单的方法是创建一个包含程序年份列的日历表。然后根本就没有逻辑,只需查询值并进行比较:
if
(select ProgramYear from dbo.Calendar where BaseDate = @StartDate) =
(select ProgramYear from dbo.Calendar where BaseDate = @EndDate)
begin
-- do something
end
此网站上有很多关于创建日历表并将其用于多种用途的帖子。根据我的经验,以这种方式使用表总是比在代码中创建公式更清晰,更易于维护。
答案 2 :(得分:0)
碰巧,12月有31天,所以无论你需要减去多少个月,你总能将结果日期范围与整年对齐,因此无论何时你的表达总是如此一个是,即使在一般情况下从其他日期开始的入学年份。
我曾经使用过一种带有一系列日期操作函数的SQL方言,这使得它比字符串twiddling更容易,如下所示:
WHERE enrolmentdate >= @YearBeg(:enrolmentdate + 6 MONTHS) - 6 MONTHS
AND enrolmentdate < @YearBeg(:enrolmentdate + 6 MONTHS) + 6 MONTHS