我必须在太平洋标准时间的某些日期之间检索行,但数据库的日期列存储为UTC。目前,我在WHERE子句中进行转换,但这需要花费大量时间,因为我在WHERE子句中使用了一个函数并导致了全表扫描。
SELECT T.foo
FROM table T
JOIN .... ON ....
WHERE CONVERT(DATETIME,SWITCHOFFSET(T.start_date_utc,DATEPART(TZOFFSET, T.start_date_utc AT TIME ZONE 'Pacific Standard Time'))) BETWEEN '1/1/2018 00:00:00 AM' AND '2/28/2018 23:59:59 PM'
没有WHERE子句中的转换函数,有没有更好的方法来做到这一点?
CONVERT
并且只有WHERE BETWEEN date1 AND date2
时它运行得更快,21秒。其他信息:
CONNECT SQL
和VIEW ANY DATABASE
权限,所以我不能创建任何新表,索引等。SHOWPLAN
权限,我看不到查询执行计划,以检查是否是其他导致慢查询的东西。但是,由于取出转换语句会将时间从30分钟缩短到21秒,我怀疑它就是那条线。我尝试过的:
WITH CTE AS (
SELECT T.Foo,
CONVERT(DATETIME,SWITCHOFFSET(T.start_date_utc, DATEPART(TZOFFSET, T.start_date_utc AT TIME ZONE 'Pacific Standard Time'))) as start_date_pst
)另一种方法是将输入更改为UTC。这是一次性操作,SQL更容易过滤。以下是根据您的sql版本实现相同目标的不同方法。
-- 1
WHERE T.start_date_utc
BETWEEN '1/1/2018 08:00:00 AM' /*PST to UTC*/
AND '2/28/2018 07:59:59 PM' /*PST to UTC*/
-- 2
WHERE T.start_date_utc
BETWEEN DATEADD(HOUR, 8, '1/1/2018 00:00:00 AM'), /*PST to UTC*/
AND DATEADD(HOUR, 8, '2/28/2018 23:59:59 PM' /*PST to UTC*/
-- 3
WHERE T.start_date_utc
BETWEEN SWITCHOFFSET('1/1/2018 00:00:00 AM', '-08:00') /*PST to UTC*/
AND SWITCHOFFSET('2/28/2018 23:59:59 PM', '-08:00') /*PST to UTC*/
/*Avoiding hard coded values*/
-- 4
DECLARE @offset INT
SELECT @offset = DATEPART(TZOFFSET, CONVERT(datetime,'1/1/2018 00:00:00 AM') AT TIME ZONE 'Pacific Standard Time') * -1
WHERE T.start_date_utc
BETWEEN DATEADD(MINUTE, @offset, '1/1/2018 00:00:00 AM'), /*PST to UTC*/
AND DATEADD(MINUTE, @offset, '2/28/2018 23:59:59 PM' /*PST to UTC*/
-- 5
WHERE T.start_date_utc
BETWEEN CONVERT(datetime,'1/1/2018 00:00:00 AM') AT TIME ZONE 'Pacific Standard Time' /*PST to UTC*/
AND CONVERT(datetime,'2/28/2018 23:59:59 PM') AT TIME ZONE 'Pacific Standard Time' /*PST to UTC*/
现在,您正在针对所有数据进行时区转换。相反,找出正确的UTC时间戳应该是什么,然后将您的数据与之比较。像这样:
declare @startTimePST datetime = '1/1/2018 00:00:00 AM',
@endTimePST datetime = '2/28/2018 23:59:59 PM';
declare @startTimeUTC datetime = @startTimePST
at time zone 'Pacific Standard Time'
at time zone 'UTC',
@endTimeUTC datetime = @endTimePST
at time zone 'Pacific Standard Time'
at time zone 'UTC';
select @startTimePST, @startTimeUTC,
@endTimePST, @endTimeUTC
SELECT T.foo
FROM table T
JOIN .... ON ....
WHERE T.start_date_utc BETWEEN @startTimeUTC AND @endTimeUTC;
通过说明,我将声明变量并为它们分配代表您的PST时间戳的值。然后我通过双重使用at time zone
子句将它们转换为UTC。为什么两个?第一个将PST时区附加到您的无时区时间戳,然后将其转换为UTC。一旦我有了这些端点,我就可以直接在查询中使用它们。