Лучший способ проверить текущую дату в предложении где SQL-запрос - PullRequest
6 голосов
/ 28 ноября 2008

Я пытаюсь найти наиболее эффективный (лучший по производительности) способ проверки поля даты на текущую дату. В настоящее время мы используем:

SELECT     COUNT(Job) AS Jobs
FROM         dbo.Job
WHERE     (Received BETWEEN DATEADD(d, DATEDIFF(d, 0, GETDATE()), 0)
                        AND DATEADD(d, DATEDIFF(d, 0, GETDATE()), 1))

Ответы [ 7 ]

13 голосов
/ 28 ноября 2008
WHERE
  DateDiff(d, Received, GETDATE()) = 0

Редактировать: Как указано в комментариях к этому ответу, это не идеальное решение. Проверьте другие ответы в этой теме, тоже.

9 голосов
/ 28 ноября 2008

Если вы просто хотите найти все записи с датой получения сегодня и есть записи с датами получения в будущем, то то, что вы делаете, (очень и очень немного) неверно ... Поскольку оператор Between допускает значения которые равны конечной границе, поэтому вы можете получить записи с Полученной датой = до полуночи завтра ...

Если нет необходимости использовать индекс для Received, все, что вам нужно сделать, это проверить, что разность дат с текущим datetime равна 0 ...

Where DateDiff(day, received, getdate()) = 0

Этот предикат, конечно, не SARGable, поэтому он не может использовать индекс ... Если это проблема для этого запроса, то при условии, что у вас не будет дат получения в будущем, я бы использовал это вместо ...

Where Received >= DateAdd(day, DateDiff(Day, 0, getDate()), 0) 

Если полученные даты могут быть в будущем, то вы, вероятно, настолько близки к наиболее эффективным, насколько это возможно ... (За исключением изменения параметра Между на> = И <) </p>

5 голосов
/ 01 декабря 2008

Если вам нужна производительность, вы хотите прямое попадание в индекс, без каких-либо ЦП и т. Д. На строку; таким образом, я бы сначала вычислил диапазон , а затем использовал простой запрос WHERE. Я не знаю, какую БД вы используете, но в SQL Server работает следующее:

// ... where @When is the date-and-time we have (perhaps from GETDATE())
DECLARE @DayStart datetime, @DayEnd datetime
SET @DayStart = CAST(FLOOR(CAST(@When as float)) as datetime) -- get day only
SET @DayEnd = DATEADD(d, 1, @DayStart)

SELECT     COUNT(Job) AS Jobs
FROM         dbo.Job
WHERE     (Received >= @DayStart AND Received < @DayEnd)
0 голосов
/ 28 ноября 2008

Я бы обычно использовал решение , предложенное Томалаком , но если вы действительно отчаянно нуждаетесь в производительности, лучшим вариантом может быть добавление дополнительного проиндексированного поля ReceivedDataPartOnly, которое будет хранить данные без временной части, а затем используйте запрос

declare @today as datetime
set @today = datediff(d, 0, getdate())

select     
    count(job) as jobs
from         
    dbo.job
where     
    received_DatePartOnly = @today
0 голосов
/ 28 ноября 2008

Как насчет

 WHERE
      DATEDIFF(d, Received, GETDATE()) = 0
0 голосов
/ 28 ноября 2008

Я не уверен, как вы определяете "лучший", но это будет работать нормально.

Однако, если этот запрос вы собираетесь выполнять неоднократно, вам следует избавиться от функции get_date () и просто вставить туда значение литеральной даты на любом языке программирования, на котором вы ее выполняете. Несмотря на их вывод изменяясь только один раз каждые 24 часа, get_date (), current_date () и т. д. являются недетерминированными функциями, что означает, что ваша СУБД, вероятно, сделает недействительным запрос в качестве кандидата для сохранения в своем кеше запросов, если он есть один.

0 голосов
/ 28 ноября 2008

это в значительной степени лучший способ сделать это. Вы можете поместить DATEADD (d, DATEDIFF (d, 0, GETDATE ()), 0) и DATEADD (d, DATEDIFF (d, 0, GETDATE ()), 1) в переменные и использовать их вместо, но я не думаю, что это улучшит производительность.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...