这是我遇到的问题:我有一个大型查询需要比较where子句中的日期时间,以查看两个日期是否在同一天。我当前的解决方案很糟糕,就是将日期时间发送到UDF中,将它们转换为当天的午夜,然后检查这些日期是否相等。当涉及到查询计划时,这是一场灾难,几乎所有UDF都在联接或where子句中。这是我的应用程序中唯一的地方之一,我没有能够根除这些函数并为查询优化器提供实际可用于查找最佳索引的内容。在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
[编辑]
我纳入@托德的建议:
where datediff(day, dateadd(hh, tz.Offset +
case when ds.LocalTimeZone is not null
then 1 else 0 end, t.TheDateINeedToCheck), @ActivityDate) = 0
我对于如何运作的误解(同一天连续几年的年收益率为366,而不是我所期望的),这使我浪费了很多精力。
但是查询计划没有改变。我认为我需要回到整个绘图板。
请参阅马克布拉克特的答案,这是**右**。我意识到你的问题是2岁,但请让我们不要让人们走错了访问这个问题的错误路径。 Todd Tingen的回答很有效,但是表现糟糕,就像你在当时发现的那样! – ErikE 2010-09-12 22:47:50
Mark的答案对于这种情况是正确的,因为优化器依赖于它。我使用dateadd的方式是一个简单而简明的方法,以查看两个日期是否在同一日历日,这是原始问题。 – Todd 2010-12-15 03:30:24