Вот проблема, с которой я сталкиваюсь: у меня есть большой запрос, который должен сравнивать datetimes в предложении where, чтобы увидеть, совпадают ли две даты в один день. Мое текущее решение, которое отстойно, заключается в том, чтобы отправить данные в UDF, чтобы преобразовать их в полночь того же дня, а затем проверить эти даты для равенства. Когда дело доходит до плана запроса, это катастрофа, как и почти все UDF в соединениях или в тех случаях, когда предложения. Это одно из единственных мест в моем приложении, что я не смог искоренить функции и дать оптимизатору запросов что-то, что он действительно может использовать, чтобы найти лучший индекс.Что такое хороший способ проверить, находятся ли два дня в одном календаре в TSQL?
В этом случае объединение кода функции в запрос кажется нецелесообразным.
Я думаю, что мне не хватает чего-то простого здесь.
Вот эта функция для справки.
if not exists (select * from dbo.sysobjects
where id = object_id(N'dbo.f_MakeDate') and
type in (N'FN', N'IF', N'TF', N'FS', N'FT'))
exec('create function dbo.f_MakeDate() returns int as
begin declare @retval int return @retval end')
go
alter function dbo.f_MakeDate
(
@Day datetime,
@Hour int,
@Minute int
)
returns datetime
as
/*
Creates a datetime using the year-month-day portion of @Day, and the
@Hour and @Minute provided
*/
begin
declare @retval datetime
set @retval = cast(
cast(datepart(m, @Day) as varchar(2)) +
'/' +
cast(datepart(d, @Day) as varchar(2)) +
'/' +
cast(datepart(yyyy, @Day) as varchar(4)) +
' ' +
cast(@Hour as varchar(2)) +
':' +
cast(@Minute as varchar(2)) as datetime)
return @retval
end
go
В довершение Я присоединяюсь в таблицах часовых поясов, чтобы проверить дату против местного времени, которое может быть различным для каждой строки:
where
dbo.f_MakeDate(dateadd(hh, tz.Offset +
case when ds.LocalTimeZone is not null
then 1 else 0 end, t.TheDateINeedToCheck), 0, 0) = @activityDateMidnight
[Редактировать]
I в том числе @ Предложение Тодда:
where datediff(day, dateadd(hh, tz.Offset +
case when ds.LocalTimeZone is not null
then 1 else 0 end, t.TheDateINeedToCheck), @ActivityDate) = 0
Мое неправильное представление о том, как работает fariff (в тот же день года в год подряд дает 366, а не 0, как я ожидал) заставил меня потратить много усилий.
Но план запроса не изменился. Думаю, мне нужно вернуться к чертежной доске со всем этим.
См. Ответ Марка Брэкетта, который является ** правым ** одним. Я понимаю, что ваш вопрос - 2 года, но, пожалуйста, давайте не будем приводить людей к неправильному пути, которые посещают этот вопрос. Ответ Тодда Тингена работает, но это ужасное исполнение, как вы нашли в то время! – ErikE 2010-09-12 22:47:50
Ответ от Марка правилен для этой ситуации, потому что оптимизатор зависит от нее. Используя dateadd, как я это сделал, это простой и сжатый способ проверить, соответствуют ли две даты одному календарному дню, который был исходным вопросом. – Todd 2010-12-15 03:30:24