Как зайти в Даркнет?!
25th January, 01:11
6
0
Как в tkinter из поля ввода Entry получить значение в одну переменную и обновить строку кнопкой, затем получить ещё одно введённое значение и затем сложить их. Ниже пример кода
21st July, 19:00
895
0
Программа, которая создает фейковые сервера в поиске игровых серверов CS 1.6 Steam
21st March, 17:43
948
0
Очень долго работает Update запрос Oracle
27th January, 09:58
914
0
не могу запустить сервер на tomcat HTTP Status 404 – Not Found
21st January, 18:02
906
0
Где можно найти фрилансера для выполнения поступающих задач, на постоянной основе?
2nd December, 09:48
938
0
Разработка мобильной кроссплатформенной военной игры
16th July, 17:57
1724
0
период по дням
25th October, 10:44
3955
0
Пишу скрипты для BAS только на запросах
16th September, 02:42
3720
0
Некорректный скрипт для закрытия блока
14th April, 18:33
4613
0
прокидывать exception в блоках try-catch JAVA
11th March, 21:11
4381
0
Помогите пожалуйста решить задачи
24th November, 23:53
6086
0
Не понимаю почему не открывается детальное описание продукта
11th November, 11:51
4351
0
Нужно решить задачу по программированию на массивы
27th October, 18:01
4396
0
Метода Крамера С++
23rd October, 11:55
4309
0
помогите решить задачу на C++
22nd October, 17:31
4002
0
Помогите решить задачу на python с codeforces
22nd October, 11:11
4492
0
Python с нуля: полное руководство для начинающих
18th June, 13:58
2599
0
Какой хороший способ проверить, находятся ли две даты в один и тот же календарный день в TSQL?
Вот проблема, с которой я сталкиваюсь: у меня есть большой запрос, который должен сравнить даты в предложении where, чтобы увидеть, если две даты находятся в один и тот же день. Мое текущее решение, которое отстойно, состоит в том, чтобы отправить даты в UDF, чтобы преобразовать их в полночь того же дня, а затем проверить эти даты на равенство. Когда дело доходит до плана запроса, это катастрофа, как и почти все UDFs в предложениях joins или 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
Чтобы усложнить ситуацию, я подключаюсь к таблицам часовых поясов, чтобы проверить дату по местному времени, которое может отличаться для каждой строки:
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
[Редактировать]
Я включаю предложение @Todd's:
where datediff(day, dateadd(hh, tz.Offset +
case when ds.LocalTimeZone is not null
then 1 else 0 end, t.TheDateINeedToCheck), @ActivityDate) = 0
Мое неправильное представление о том, как работает datediff (один и тот же день года в последовательные годы дает 366, а не 0, как я ожидал), заставило меня потратить много усилий.
Но план запроса не изменился. Я думаю, что мне нужно вернуться к чертежной доске со всем этим.
Вы в значительной степени должны держать левую сторону вашего пункта where чистой. Поэтому, как правило, вы делаете что-то вроде:
WHERE MyDateTime >= @activityDateMidnight
AND MyDateTime < (@activityDateMidnight + 1)
(Некоторые люди предпочитают DATEADD (d, 1, @activityDateMidnight) вместо этого - но это одно и то же).
Однако таблица TimeZone немного усложняет дело. Это немного неясно из вашего фрагмента, но похоже, что t.TheDateInTable находится в GMT с идентификатором часового пояса, и что вы затем добавляете смещение для сравнения с @activityDateMidnight - который находится в локальном времени. Хотя я не уверен, что такое ds.LocalTimeZone.
Если это так, то вместо этого вам нужно получить @activityDateMidnight в GMT.
Убедитесь, что только чтение в базе данных может получить улучшение 1000% +, изменив несколько строк кода , чтобы Вы были уверены, что оптимизатор может эффективно использовать индекс при работе с датами
Эрик З Бородой:
Я действительно храню все даты в GMT. Вот пример использования: что-то произошло в 11:00 вечера по восточному времени 1-го числа, то есть 2-го числа GMT. Я хочу увидеть активность для 1-го, и я нахожусь в EST, поэтому я хочу увидеть активность в 11 вечера. Если бы я просто сравнил raw GMT datetimes, я бы все пропустил. Каждая строка отчета может представлять действие из другого часового пояса.
Правильно, но когда вы говорите, что вас интересует деятельность за 1 января 2008 года EST:
SELECT @activityDateMidnight = '1/1/2008', @activityDateTZ = 'EST'
вам просто нужно преобразовать его в GMT (я игнорирую сложность запроса за день до того, как EST перейдет в EDT, или наоборот):
Table: TimeZone
Fields: TimeZone, Offset
Values: EST, -4
--Multiply by -1, since we're converting EST to GMT.
--Offsets are to go from GMT to EST.
SELECT @activityGmtBegin = DATEADD(hh, Offset * -1, @activityDateMidnight)
FROM TimeZone
WHERE TimeZone = @activityDateTZ
что должно дать вам "1/1/2008 4:00 AM". Тогда вы можете просто искать в GMT:
SELECT * FROM EventTable
WHERE
EventTime >= @activityGmtBegin --1/1/2008 4:00 AM
AND EventTime < (@activityGmtBegin + 1) --1/2/2008 4:00 AM
Событие, о котором идет речь, хранится с GMT EventTime из 1/2/2008 3:00 AM. Вам даже не нужно TimeZone в EventTable (по крайней мере, для этой цели).
Поскольку EventTime не входит в функцию, это прямое сканирование индекса, которое должно быть довольно эффективным. Сделайте EventTime своим кластеризованным индексом,и он полетит. ;)
Лично я бы попросил приложение преобразовать время поиска в GMT перед запуском запроса.
Эрик З Бородой:
дата активности предназначена для указания местного часового пояса, но не конкретного
Ладно, вернемся к чертежной доске. Попробовать это:
where t.TheDateINeedToCheck BETWEEN (
dateadd(hh, (tz.Offset + ISNULL(ds.LocalTimeZone, 0)) * -1, @ActivityDate)
AND
dateadd(hh, (tz.Offset + ISNULL(ds.LocalTimeZone, 0)) * -1, (@ActivityDate + 1))
)
который переведет @ActivityDate в местное время и сравнит с этим. Это ваш лучший шанс для использования индекса, хотя я не уверен, что он будет работать - вы должны попробовать его и проверить план запроса.
Следующим вариантом будет индексированное представление с индексированным, вычисленным TimeINeedToCheck по местному времени . А потом ты просто возвращаешься к себе.:
where v.TheLocalDateINeedToCheck BETWEEN @ActivityDate AND (@ActivityDate + 1)
что, безусловно, будет использовать индекс - хотя у вас есть небольшие накладные расходы на INSERT и UPDATE тогда.
Вы избалованы выбором с точки зрения вариантов здесь. Если вы используете Sybase или SQL Server 2008, Вы можете создать переменные типа date и назначить им свои значения datetime. Компонент database engine избавляет вас от этого времени. Вот быстрый и грязный тест, чтобы проиллюстрировать (код находится в диалекте Sybase):
declare @date1 date
declare @date2 date
set @date1='2008-1-1 10:00'
set @date2='2008-1-1 22:00'
if @date1=@date2
print 'Equal'
else
print 'Not equal'
Для SQL 2005 и более ранних версий можно преобразовать дату в varchar в формате, не содержащем компонент time. Например, следующее возвращает 2008.08.22
select convert(varchar,'2008-08-22 18:11:14.133',102)
В 102 части указывается форматирование (Books online может перечислить для вас все доступные форматы)
Итак, что вы можете сделать, так это написать функцию, которая берет datetime и извлекает элемент даты и отбрасывает время. Вот так:
create function MakeDate (@InputDate datetime) returns datetime as
begin
return cast(convert(varchar,@InputDate,102) as datetime);
end
Затем вы можете использовать эту функцию для компаньонов
Select * from Orders where dbo.MakeDate(OrderDate) = dbo.MakeDate(DeliveryDate)