2011-12-14 2 views
2

Я работаю с более старой базой кода, где краткость не встречается во многих местах.Являются ли эти две части кода SQL одинаковыми?

Один фрагмент кода, который мы постоянно используем в базе данных, состоит в том, чтобы определить, находятся ли две даты в одном и том же программном году. Например, программа Год 2011 начинается с 1 июля 2011 года и заканчивается 1 июль 2012 (или технически день раньше)

Обычным способом я вижу, что эта проблема решается путем использования такого кода:

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))' 

Перед тем, как перейти введения новых ошибок в системе, которая «просто работает» , Я бы хотел спросить об этом. Являются ли эти два кода одинаковыми? Будут ли они всегда давать одинаковый результат (при условии действительных дат)?

ответ

1

Проблема, которую я вижу, заключается в том, что в зависимости от оптимизатора ваше решение (которое выглядит лучше) может не использовать индекс, определенный в ENROLLMENTDATE, поскольку вы выполняете на нем операции, в то время как исходное решение будет. Если в этом поле нет указателей, я не вижу проблемы.

+0

+1 ... все еще не убежден, что последняя форма одинаков, но даже если это так, она получит серьезный удар по производительности, поскольку она не сможет использовать индексы на EnrollmentDate с пользой (если вообще) , –

0

Как это бывает, декабрь имеет 31 день, поэтому независимо от того, сколько месяцев вам нужно вычесть, вы всегда сможете выровнять полученный результат и поэтому ваше выражение всегда будет истинным, когда исходный был, даже в общем случае, для периода регистрации, начиная с других дат.

однажды я использовал диалект SQL с набором функций даты манипуляции, которые сделали это немного легче, чем строка кручений-верчения, что-то вроде этого:

WHERE enrolmentdate >= @YearBeg(:enrolmentdate + 6 MONTHS) - 6 MONTHS 
    AND enrolmentdate < @YearBeg(:enrolmentdate + 6 MONTHS) + 6 MONTHS 
1

еще более простого способа справиться с этой ситуацией, чтобы создать таблица календаря со столбцом для программного года. Тогда нет никакой логики вообще, вы просто запросить значения и сравнить их:

if 
(select ProgramYear from dbo.Calendar where BaseDate = @StartDate) = 
(select ProgramYear from dbo.Calendar where BaseDate = @EndDate) 
begin 
-- do something 
end 

Есть много сообщений на этом сайте о создании календаря таблиц и использовать их для различных целей. По моему опыту, использование таблицы таким образом всегда яснее и удобнее, чем создавать формулы в коде.