SQL - Правильное предложение "где" для текущего месяца - PullRequest
1 голос
/ 30 ноября 2011

Как правильно проверить события текущего месяца на SQL Server и почему?

1) WHERE (DATEDIFF(month, EventTime, GETDATE())=0))

2) WHERE (YEAR(EventTime) = YEAR(GETDATE()) AND MONTH(EventTime) = MONTH(GETDATE()))

Формат датыв таблице то есть EventTime: 2011-11-30 15:68:25.000

Ответы [ 5 ]

7 голосов
/ 30 ноября 2011

У меня нет доступа к SQL Server с профилировщиком, поэтому я не могу дать столь подробный ответ, как мне хотелось бы.

Вопрос в основном в том, какой из них позволяетвычисление и наиболее эффективное использование индексов.

Варианты, которые используют манипуляции со строками, имеют наибольшую вычислительную нагрузку и вообще не используют индексы.Так что я просто пропущу это.Это оставляет четыре общих выражения ...

SELECT * FROM date_sargable
WHERE  YEAR(value) = YEAR (getDate())
  AND MONTH(value) = MONTH(getDate())
;

SELECT * FROM date_sargable
WHERE DATEDIFF(MONTH, value, getDate()) = 0
;

SELECT * FROM date_sargable
WHERE DATEDIFF(MONTH, 0, value) = DATEDIFF(MONTH, 0, getDate())
;


SELECT * FROM date_sargable
WHERE value >= DATEADD(MONTH, DATEDIFF(MONTH, 0, getDate())    , 0)
  AND value <  DATEADD(MONTH, DATEDIFF(MONTH, 0, getDate()) + 1, 0)
;

Первые три используют INDEX SCAN, но последнее использует INDEX SEEK.Разница в том, что формат запроса позволяет оптимизатору узнать, что вам нужен определенный диапазон данных, что все они расположены рядом друг с другом в одном блоке индекса, и что этот блок очень легко найти.

Если, просматривая планы выполнения, вы видите SEEK в одной версии и SCAN в другой, вы с большей вероятностью выиграете от SEEK.

4 голосов
/ 30 ноября 2011

Запись запросов для непрерывных периодов как явного условия диапазона.

http://use -the-index-luke.com / sql / where-clause / obfuscation / date

Таким образом, используйте что-то вроде этого:

WHERE EventTime between <begin-of-month> and <end-of-month>

Пример кода доступен на той же странице, хотя выполняется ежеквартальная фильтрация:

http://use-the-index-luke.com/sql/where-clause/obfuscation/dates?dbtype=sqlserver#sample_quarter_begin_end

Почему? Для упрощения индексации.

1 голос
/ 30 ноября 2011

Если у вас есть индекс для этого столбца, то оба вычисления обходят индекс, потому что вы используете не то, для чего индексирован столбец, а только часть индекса

WHERE (DATEDIFF(month, EventTime, GETDATE())=0))
WHERE (YEAR(EventTime) = YEAR(GETDATE()) AND MONTH(EventTime) = MONTH(GETDATE()))

Вам гораздо лучше использовать что-то подобное

WHERE EventTime BETWEEN Cast (DATEADD(dd,-(DAY(GetDate())-1),GetDate()) as Date)
                AND Cast (DATEADD(dd,-(DAY(DATEADD(mm,1,GetDate()))),DATEADD(mm,1,GetDate())) as Date)

Вы также можете использовать ту же концепцию с >= и <= для дат

1 голос
/ 30 ноября 2011

По логике, они оба.

Тем не менее, я думаю, что первое проще (одно условие вместо двух), легче для понимания и с большей вероятностью может быть искажено - поэтому я предлагаю использовать это.

0 голосов
/ 25 сентября 2014

Один совет очень прост, используя функцию to_char , посмотрите:

На пример даты:

2011-11-30 15: 68: 25.000

Вы можете сделать это:

to_char (your_field, 'MM') = 11

или для текущего месяца системной даты:

to_char ( sysdate , 'MM') = 11

Одна деталь, to_char функцияподдерживается языком SQL, а не одной конкретной базой данных.

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