SQL Server, как избежать преобразования часовых поясов в предложении WHERE - PullRequest
0 голосов
/ 09 апреля 2019

Мне нужно получить строки между определенными датами Стандартное тихоокеанское время , но в базе данных есть столбец даты, сохраненный как 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?

  • Запрос принимает30 минут, но когда я удаляю CONVERT и просто WHERE BETWEEN date1 AND date2, он работает намного быстрее, 21 секунда.
  • Конечно, приветствуются и другие предложения, если есть лучшее решение, чем сравнение дат с оператором преобразования.

Другая информация:

  • У меня есть только разрешения CONNECT SQL и VIEW ANY DATABASE, поэтому я не могу создавать любые новые таблицы, индексы и т. д.

  • Без разрешений SHOWPLAN я не вижу план выполнения запроса , чтобы проверить, вызывает ли это что-то ещемедленный запрос.Но так как удаление оператора преобразования приносит время от 30 минут до 21 секунды, я подозреваю, что это та строка.

  • Я использую Microsoft SQL Server Management Studio 17

  • Windows 7

Что я пробовал:

  • Я пытался создать общийтаблица и преобразование столбца даты перед основным запросом, но это все так же медленно.Вероятно, поскольку преобразование все еще должно происходить в каждой строке.

    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)

Ответы [ 2 ]

2 голосов
/ 09 апреля 2019

Другой подход заключается в изменении ввода на 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*/
1 голос
/ 09 апреля 2019

Прямо сейчас вы выполняете преобразование часового пояса для всех ваших данных. Вместо этого выясните, какими должны быть правильные метки времени 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. Затем я конвертирую их в UTC путем двойного использования предложения at time zone. Почему два? Первый прикрепляет часовой пояс PST к вашим временным меткам без часового пояса, а затем преобразует эти в UTC. Когда у меня есть эти конечные точки, я могу использовать их непосредственно в запросе.

...