MySQL SELECT WHERE datetime соответствует дню (и не обязательно времени)


127

У меня есть таблица, содержащая столбец datetime. Я хочу вернуть все записи за определенный день независимо от времени. Или, другими словами, если моя таблица содержит только следующие 4 записи, тогда будут возвращены только 2-я и 3-я, если я ограничусь 2012-12-25.

2012-12-24 00:00:00
2012-12-25 00:00:00
2012-12-25 06:00:00
2012-12-26 05:00:00

См. Ответ Джона Ву на stackoverflow.com/questions/14769026/…
ekerner

Ответы:


326

НИКОГДА не используйте селектор вроде DATE(datecolumns) = '2012-12-24'- это убийца производительности:

  • он будет рассчитывать DATE()для всех строк, включая те, которые не соответствуют
  • это сделает невозможным использование индекса для запроса

Гораздо быстрее использовать

SELECT * FROM tablename 
WHERE columname BETWEEN '2012-12-25 00:00:00' AND '2012-12-25 23:59:59'

так как это позволит использовать индекс без расчета.

РЕДАКТИРОВАТЬ

Как указывает Used_By_Already, за время, прошедшее с момента первоначального ответа в 2012 году, появились версии MySQL, в которых использование «23:59:59» в качестве конца дня уже небезопасно. Обновленная версия должна читать

SELECT * FROM tablename 
WHERE columname >='2012-12-25 00:00:00'
AND columname <'2012-12-26 00:00:00'

Суть ответа, то есть отказ от селектора в вычисляемом выражении, конечно же, остается в силе.


Я собирался прокомментировать, что решение a1ex07 не так хорошо, как другие. Прочитав ваш пост, возможно, мне нужно перевернуть свое мышление!
user1032531

2
Только что протестировано на двух серверах, это НАМНОГО (как минимум в 10 раз) быстрее, чем date () = '', особенно для огромных таблиц. Спасибо
zzapper

1
@KonradViltersten Я использовал очень подробный способ сформулировать запрос, чтобы сделать его более читаемым и довести до конца свою точку зрения, не уточняя ее. Ответ a1ex07 имеет разреженный синтаксис.
Eugen Rieck

9
@KonradViltersten - еще лучше: WHERE col >= '2012-12-25' AND col < '2012-12-25' + INTERVAL 1 DAY. Это позволяет избежать 0 раз и работает DATE, DATETIME, DATETIME(6)и т.д. И дело с високосного дня и т.д.
Рик Джеймс

1
«2012-12-25 23:59:59» НЕ ДЕЙСТВИТЕЛЬНО в качестве конца дня, это всегда было плохой идеей, и это вызовет ошибки для версий MySQL, которые поддерживают точность до секунды. Намного лучше использовать подход Рика Джеймса (см. Выше) или a1ex07 (другой ответ)
Used_By_Already

34

... WHERE date_column >='2012-12-25' AND date_column <'2012-12-26'потенциально может работать лучше (если у вас есть индекс для date_column), чем DATE.


1
Мне вообще интересно, что быстрее - это или BETWEENрешение ... кто-нибудь пометил?
jave.web

6
Никакой разницы быть не должно. BETWEENэто просто способ писать field >= value1 and fied<= value2.
a1ex07

1
Обратите внимание, что в соответствии с Руководством по MySQL: «Для достижения наилучших результатов при использовании BETWEEN со значениями даты или времени используйте CAST () для явного преобразования значений в требуемый тип данных. Примеры: Если вы сравниваете DATETIME с двумя значениями DATE, преобразуйте DATE значения в значения DATETIME. Если вы используете строковую константу, такую ​​как '2001-1-1', в сравнении с DATE, приведите строку к DATE. " Поэтому, если все они не одного типа, лучше явно привести их.
techdude

21

Вы можете использовать %:

SELECT * FROM datetable WHERE datecol LIKE '2012-12-25%'

13
LIKE кажется таким же медленным, как DATE (datetimecol). Лучше использовать решение Евгения или a1ex07.
Мари Фишер

3
Дело не всегда в скорости. Так что мне нравится это решение. Это намного читабельнее.
Саймон Хансен
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.