Eri*_*ard 23 sql t-sql sql-server datetime user-defined-functions
这是我遇到的问题:我有一个大型查询需要比较where子句中的日期时间,以查看两个日期是否在同一天.我当前的解决方案很糟糕,是将日期时间发送到UDF以将它们转换为同一天的午夜,然后检查这些日期是否相等.当涉及到查询计划时,这是一场灾难,几乎所有联接中的UDF或where子句都是如此.这是我的应用程序中唯一一个我无法根除函数并为查询优化器提供实际可用于查找最佳索引的地方之一.
在这种情况下,将函数代码合并回查询似乎是不切实际的.
我想我在这里缺少一些简单的东西.
这是参考功能.
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
Run Code Online (Sandbox Code Playgroud)
更复杂的是,我正在加入时区表来检查当地时间的日期,每行可能会有所不同:
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
Run Code Online (Sandbox Code Playgroud)
[编辑]
我正在纳入@Todd的建议:
where datediff(day, dateadd(hh, tz.Offset +
case when ds.LocalTimeZone is not null
then 1 else 0 end, t.TheDateINeedToCheck), @ActivityDate) = 0
Run Code Online (Sandbox Code Playgroud)
我对约瑟夫如何工作的误解(连续几年的同一天产生366,而不是我预期的0)导致我浪费了很多精力.
但查询计划没有改变.我想我需要回到整个事情的绘图板.
小智 62
这更简洁:
where
datediff(day, date1, date2) = 0
Run Code Online (Sandbox Code Playgroud)
Mar*_*ett 19
你几乎必须保持where子句的左侧清洁.所以,通常情况下,你会这样做:
WHERE MyDateTime >= @activityDateMidnight
AND MyDateTime < (@activityDateMidnight + 1)
Run Code Online (Sandbox Code Playgroud)
(有些人更喜欢DATEADD(d,1,@ activityDateMidnight) - 但这是相同的事情).
TimeZone表虽然有点复杂.你的片段有点不清楚,但它看起来像是.DateInTable在GMT中带有时区标识符,然后你要添加偏移量来与@activityDateMidnight进行比较 - 这是当地时间.不过,我不确定ds.LocalTimeZone是什么.
如果是这种情况,那么你需要将@activityDateMidnight改为GMT.
where
year(date1) = year(date2)
and month(date1) = month(date2)
and day(date1) = day(date2)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
39546 次 |
| 最近记录: |