Как выбрать дату из столбца datetime?


238

У меня есть столбец типа «datetime» со значениями, как 2009-10-20 10:00:00

Я хотел бы извлечь дату из datetime и написать запрос как:

SELECT * FROM 
data 
WHERE datetime = '2009-10-20' 
ORDER BY datetime DESC

Это следующий лучший способ сделать это?

SELECT * FROM 
data 
WHERE datetime BETWEEN('2009-10-20 00:00:00' AND '2009-10-20 23:59:59')
ORDER BY datetime DESC

Это однако возвращает пустой набор результатов. Какие-либо предложения?

Ответы:


456

Вы можете использовать DATE()функцию MySQL :

WHERE DATE(datetime) = '2009-10-20'

Вы также можете попробовать это:

WHERE datetime LIKE '2009-10-20%'

См. Этот ответ для получения информации о влиянии на производительность использования LIKE.


2
попробовал это: Где DATE (datetime) = '2009-10-20', это работает
mysqllearner

44
Первый очень медленный и игнорирует индексы. Лучше иметь как «дата%»
kachar

ГДЕ ДАТА (дата / время) КАК '% ключевое слово%' работает, спасибо
Сильвия Зулинка

2
Я считаю, что это не работает, как ожидалось, если часовой пояс Rails отличается от UTC. Это связано с тем, что DATE () разрешает значение столбца в UTC. Таким образом, такая дата, как «Пт, 30 декабря 2016 00:00:00 SGT +08: 00», которую мы ожидаем найти, если запросить «2016-12-30», не будет найдена. Зачем? Потому что DATE () преобразует его в UTC-эквивалент перед выполнением сравнения, то есть «2016-12-29 16:00:00 UTC». Поправь меня, если я ошибаюсь, так как до недавнего времени это тоже было для меня ошибкой.
Тикибой

WHERE DATE (datetime) = '{? Sdate} отлично работает для параметра Crystal Reports! Хорошая работа!
MikeMighty

94

Использование WHERE DATE(datetime) = '2009-10-20' имеет проблемы с производительностью . Как указано здесь :

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

Используйте BETWEENили >, <, =операторы , которые позволяют использовать индекс:

SELECT * FROM data 
WHERE datetime BETWEEN '2009-10-20 00:00:00' AND '2009-10-20 23:59:59'

Обновление: воздействие на использование LIKEвместо операторов в индексированном столбце является высоким . Вот некоторые результаты теста для таблицы с 1 176 000 строками:

  • используя datetime LIKE '2009-10-20%'=> 2931мс
  • используя datetime >= '2009-10-20 00:00:00' AND datetime <= '2009-10-20 23:59:59'=> 168 мс

При повторном вызове по тому же запросу разница еще выше: 2984мс против 7мс (да, всего 7 миллисекунд!). Я нашел это, переписывая старый код в проекте, используя Hibernate.


Интересно, что если реализация MySql автоматически преобразуется DATE(datetime)в BETWEEN AND новые сцены, мы получаем короткое заявление и отличную производительность. Почему нет? Почему они этого не сделали? :)
Cherry

Потому что что-то вроде DATE(datetime) in (:list)не работает сBETWEEN
Тим

25

Вы можете отформатировать дату и время в часть YMD:

DATE_FORMAT(datetime, '%Y-%m-%d')

2
И таким образом вы можете получить только часть времени, если это необходимо:DATE_FORMAT(datetime, '%H:%i:%S')
Metafaniel

это прекрасно работает для форматирования даты и времени, но взамен база данных вернет новый массив для установки имени, просто добавив нужное имя в конце DATE_FORMAT (columnName, '% Y-% m-% d') arrayName для более подробной проверки Документация dev.mysql.com/doc/refman/8.0/en/…
Ридха Реззаг

15

Хотя все ответы на странице вернут желаемый результат, все они имеют проблемы с производительностью. Никогда не выполняйте вычисления над полями в WHEREпредложении (включая DATE()вычисление), поскольку это вычисление должно выполняться для всех строк в таблице.

BETWEEN ... ANDКонструкт включительно для обоего граничных условий, требующий один , чтобы указать 23:59:59 синтаксиса на дате окончания , который сам имеет другие проблемы (микросекунды сделку, которые я считаю , MySQL не поддерживает в 2009 году , когда был задан вопрос).

Правильный способ запросить timestampполе MySQL для определенного дня - это проверить значения Greater-Than-Equals на требуемую дату и Less-Than на следующий день без указания часа.

WHERE datetime>='2009-10-20' AND datetime<'2009-10-21'

Это самый быстрый и эффективный метод с наименьшим объемом памяти и наименьшими ресурсами, который дополнительно поддерживает все функции MySQL и такие примеры, как точность отметки времени менее секунды. Кроме того, это доказательство будущего.


1
И, используя аргумент производительности, одинаково вычисляются «> =» и «<» для каждой строки таблицы, или SQL-сервер просто «волшебным образом» знает, больше ли число, чем другое? :-)
Хавьер Герреро

@JavierGuerrero: Мой пример сравнивает две константы: одну из таблицы и строковый литерал.
dotancohen

«Один из таблицы» не является константой, она варьируется для каждой строки, поэтому для каждой строки должен быть выполнен один и тот же расчет (а также оба должны быть преобразованы во время эпохи, чтобы выполнить сравнение)
Хавьер Герреро

9

Здесь все форматы

Скажем, это столбец, который содержит datetimeзначение, таблица data.

+--------------------+
| date_created       |
+--------------------+
| 2018-06-02 15:50:30|
+--------------------+

mysql> select DATE(date_created) from data;
+--------------------+
| DATE(date_created) |
+--------------------+
| 2018-06-02         |
+--------------------+

mysql> select YEAR(date_created) from data;
+--------------------+
| YEAR(date_created) |
+--------------------+
|               2018 |
+--------------------+

mysql> select MONTH(date_created) from data;
+---------------------+
| MONTH(date_created) |
+---------------------+
|                   6 |
+---------------------+

mysql> select DAY(date_created) from data;
+-------------------+
| DAY(date_created) |
+-------------------+
|                 2 |
+-------------------+

mysql> select HOUR(date_created) from data;
+--------------------+
| HOUR(date_created) |
+--------------------+
|                 15 |
+--------------------+

mysql> select MINUTE(date_created) from data;
+----------------------+
| MINUTE(date_created) |
+----------------------+
|                   50 |
+----------------------+

mysql> select SECOND(date_created) from data;
+----------------------+
| SECOND(date_created) |
+----------------------+
|                   31 |
+----------------------+

5

Ты можешь использовать:

DATEDIFF ( day , startdate , enddate ) = 0

Или:

DATEPART( day, startdate ) = DATEPART(day, enddate)
AND 
DATEPART( month, startdate ) = DATEPART(month, enddate)
AND
DATEPART( year, startdate ) = DATEPART(year, enddate)

Или:

CONVERT(DATETIME,CONVERT(VARCHAR(12), startdate, 105)) = CONVERT(DATETIME,CONVERT(VARCHAR(12), enddate, 105))

5

простой и лучший способ использовать функцию даты

пример

SELECT * FROM 
data 
WHERE date(datetime) = '2009-10-20' 

ИЛИ

SELECT * FROM 
data 
WHERE date(datetime ) >=   '2009-10-20'  && date(datetime )  <= '2009-10-20'

-5

Что ж, использование LIKEв выражении является лучшим вариантом, WHERE datetime LIKE '2009-10-20%' оно должно работать в этом случае

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.