是否有更简洁的方法将 UTC 日期时间仅转换为本地日期?

Rac*_*hel 7 sql-server-2005 sql-server query-refactor

我正在尝试编写一个查询,该查询仅根据 UTC 日期时间字段的本地日期部分对记录进行分组。

例如,如果我的表包含10/19/2012 2:00:00,那么它应该被分组为10/18/2012,因为我的本地时间是美国东部时间 (-5h) 并且我只对字段的日期部分感兴趣。

我知道我DateAdd(day, DateDiff(day, 0, MyDate), 0)只能从日期时间字段中获取日期部分,我可以DateAdd(minute, DateDiff(minute, GetUtcDate(), GetDate()), MyUtcDate)用来将 UTC 日期时间转换为本地日期时间。

但是将两者结合起来严重冒犯了我。

在 SQL Server 2005 中,是否有比这更好的方法来获取 UTC 日期时间字段的日期部分,转换为本地时间?

  SELECT DateAdd(day, DateDiff(day, 0, DateAdd(minute, DateDiff(minute, GetUtcDate(), GetDate()), MyUtcDate)), 0)
       , Count(*)
    FROM MyTable
GROUP BY DateAdd(day, DateDiff(day, 0, DateAdd(minute, DateDiff(minute, GetUtcDate(), GetDate()), MyUtcDate)), 0)
Run Code Online (Sandbox Code Playgroud)

Han*_*non 6

如果您不反对让函数做脏活,这有助于使语句更清晰:

CREATE FUNCTION LocalDateFromUTCTime
(
    @UTCDateTime datetime
)
RETURNS datetime
BEGIN
    DECLARE @diff int;
    SET @diff = datediff(hh,GetUTCDate(), GetDate());
    RETURN DATEADD(day, DATEDIFF(day, 0, DATEADD(hh, @diff, @UTCDateTime)),0);
END
Run Code Online (Sandbox Code Playgroud)

然后,您可以执行以下操作:

SELECT dbo.LocalDateFromUTCTime(MyUTCDate), COUNT(*)
FROM MyTable
GROUP BY dbo.LocalDateFromUTCTime(MyUTCDate);
Run Code Online (Sandbox Code Playgroud)

当然,这确实使语句不可 SARGable。

如果由于您可能拥有大量记录,sargability 是主要问题,您可以创建一个物化视图,并在计算字段上设置索引。


编辑:

根据@RichardThekiwi,此特定语句的 SARGability 不受使用该函数的影响,因为该函数不是 aJOIN或 aWHERE子句的一部分。当功能使用,它是RAN将已使用的任何索引之后。

另外,不是上面的代码会截断输入到函数的日期的任何时间部分(这是设计使然)。因此,任何实施分钟的时区,例如加拿大的爱德华王子岛 (UTC -4:30)、印度 (UTC -4:30) 和加德满都 (UTC +5:45)

  • 此处的 GROUP BY 和 SELECT 是在搜索后执行的,因此 SARGability 不应该真正受到关注,恕我直言。顺便说一句,您是否知道时区有 1/2 小时的步长(非常规律),而加德满都使用`UTC/GMT +5:45`? (3认同)