Оператор BETWEEN идеально подходит для сравнения диапазона между датами (datetime). Но тут есть подводные камни. Например, есть задача — выбрать данные из таблицы за некоторый промежуток времени (с ‘2008-08-14’ по ‘2008-08-23’).
Рекомендации:
1. Выполняя любые сравнения, приводить все данные к одному типу.
2. Если один операнд имеет значение типа TIMESTAMP или DATETIME, а другой является константой, операнды сравниваются как значения типа TIMESTAMP. А это значит, что если была строка в виде ‘2008-08-14’, то она автоматически преобразуется в TIMESTAMP ‘2008-08-14 00:00:00’ и это влияет на результат запроса.
3. Над данными, которые участвуют в условиях сравнения желательно не делать никаких операций — это позволяет для них использовать индексы, иначе они игнорируются.
Примеры запросов с BETWEEN и без него:
# Поле created_at - тип DATETIME # КОРРЕКТНЫЕ ЗАПРОСЫ # 1: Индексы для created_at поля не используются. # Условие BETWEEN '2008-08-14' AND '2008-08-23' # преобразуется в BETWEEN '2008-08-14 00:00:00' AND '2008-08-23 00:00:00'. SELECT * FROM news WHERE DATE(created_at) BETWEEN '2008-08-14' AND '2008-08-23'; # 2: Оператор BETWEEN не используем, но тоже не самый лучший вариант, индексы не используются SELECT * FROM news WHERE DATE(created_at) >= '2008-08-14' AND DATE(created_at) <= '2008-08-23'; # 3: Строки '2008-08-14 00:00:00' и '2008-08-23 23:59:59' не приведены к типу данных DATE SELECT * FROM news WHERE created_at BETWEEN '2008-08-14 00:00:00' AND '2008-08-23 23:59:59'; # 4: Самый лучший вариант, привели к типу DATETIME, индексы будут использоваться SELECT * FROM news WHERE created_at BETWEEN STR_TO_DATE('2008-08-14 00:00:00', '%Y-%m-%d %H:%i:%s') AND STR_TO_DATE('2008-08-23 23:59:59', '%Y-%m-%d %H:%i:%s'); ############################# # НЕПРАВИЛЬНЫЕ ЗАПРОСЫ # 5: Строки '2008-08-14' и '2008-08-23' преобразуются в TIMESTAMP и дополняются '00:00:00' SELECT * FROM news WHERE created_at >= '2008-08-14' AND created_at <= '2008-08-23'; # 6: Аналогично запросу 5 SELECT * FROM news WHERE created_at BETWEEN STR_TO_DATE('2008-08-14', '%Y-%m-%d') AND STR_TO_DATE('2008-08-23', '%Y-%m-%d');
Получаем самый лучший запрос:
SELECT * FROM news WHERE created_at BETWEEN STR_TO_DATE('2008-08-14 00:00:00', '%Y-%m-%d %H:%i:%s') AND STR_TO_DATE('2008-08-23 23:59:59', '%Y-%m-%d %H:%i:%s');
Ссылки по теме:
• MySQL 5.1 Reference Manual :: 11.2.3 Comparison Functions and Operators :: Operator BETWEEN
• MySQL 5.1 Reference Manual :: 11 Functions and Operators :: 11.6 Date and Time Functions
• Search by Date or Timestamp in MySQL
Май 27th, 2009 at 16:48
автору респект.
Очень доходчиво
Август 27th, 2009 at 10:03
А в случае если дату брать как TIMESTAMP, по идее индексы должны работать
пример:
SELECT * FROM `ps_feed` WHERE created_at BETWEEN TIMESTAMP(‘2009-08-20’) AND TIMESTAMP(‘2009-08-27’)
Сентябрь 8th, 2009 at 09:36
«Самый лучший» у меня запрос не работает. Но за то прекрасно работает
SELECT * FROM news WHERE calldate BETWEEN ‘2009-09-03%’ AND ‘2009-09-08%’
где calldate — типа datetime
Сентябрь 16th, 2009 at 10:10
SELECT * FROM news WHERE DATE(calldate) BETWEEN ‘2009-09-03’ AND ‘2009-09-08’
Октябрь 25th, 2009 at 15:39
[…] MySQL: cравнение даты (datetime) через оператор BETWEEN […]
Декабрь 15th, 2009 at 11:47
Автору — спасибо.
Кратко, чётко и без «писательских соплей». 8)
Больше бы таких статей в интернете.
Март 12th, 2010 at 17:08
Спасибо автору!
Как раз то, что я искал)!
Июнь 1st, 2011 at 13:57
Хорошая статья.
Можно спросить. А чем плох 3-й вариант. Обязательно строки приводить к типу данных DATE ?
Июнь 11th, 2011 at 21:09
В 4-м варианте мы явно приводим данные к нужному типу — и сюрпризов в этом случае не будет. 3-й вариант тоже будет работать. Стоит всегда проверять запросы с помощью EXPLAIN — и выбирать лучший запрос.