這是我遇到的問題:我有一個大型查詢需要比較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