Reputation: 63895
I'm working with a bit of an older code base where conciseness is not found in many places.
One piece of code we are constantly using in the database is to determine if two dates are within the same program year. For instance, Program Year 2011 begins on July 1st, 2011 and ends on July 1st, 2012(or technically the day before)
The usual way I see that this problem is solved is by using this kind of code:
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)
I recently happened to have to solve this problem and the instant thing that popped in my head was something much more concise:
where year(dateadd(mm,-6,ENROLLMENTDATE)) = year(dateadd(mm,-6,@EnrollmentDate))'
Before I go introducing new bugs into a system that "just works", I'd like to ask SO about this. Are these two pieces of code exactly the same? Will they always give the same output(assuming valid dates)?
Upvotes: 2
Views: 95
Reputation: 16260
An even easier way to handle this situation is to create a calendar table with a column for the program year. Then there is no logic at all, you just query the values and compare them:
if
(select ProgramYear from dbo.Calendar where BaseDate = @StartDate) =
(select ProgramYear from dbo.Calendar where BaseDate = @EndDate)
begin
-- do something
end
There are many posts on this site about creating calendar tables and using them for many different purposes. In my experience, using a table in this way is always clearer and more maintainable than creating formulas in code.
Upvotes: 1
Reputation: 55402
As it happens, December has 31 days, so no matter how many months you need to subtract, you will always be able to align the resulting date range with a whole year, and therefore your expression will always be true whenever the original one was, even in the general case for an enrolment year starting on other dates.
I once used a dialect of SQL with a range of date manipulation functions that made this slightly easier than string twiddling, something like this:
WHERE enrolmentdate >= @YearBeg(:enrolmentdate + 6 MONTHS) - 6 MONTHS
AND enrolmentdate < @YearBeg(:enrolmentdate + 6 MONTHS) + 6 MONTHS
Upvotes: 0
Reputation: 4183
the problem I see is that, depending on the optimizer, your solution (that looks better) may not use an index defined on ENROLLMENTDATE since you're doing operations on it, while the original solution would. If there are no indexes on that field, then I don't see an issue
Upvotes: 1