Оператор BETWEEN идеально подходит для сравнения диапазона между датами (datetime). Но тут есть подводные камни. Например, есть задача — выбрать данные из таблицы за некоторый промежуток времени (с ’2008-08-14′ по ’2008-08-23′).
Рекомендации:
1. Выполняя любые сравнения, приводить все данные к одному типу.
2. Если один операнд имеет значение типа TIMESTAMP или DATETIME, а другой является константой, операнды сравниваются как значения типа TIMESTAMP. А это значит, что если была строка в виде ’2008-08-14′, то она автоматически преобразуется в TIMESTAMP ’2008-08-14 00:00:00′ и это влияет на результат запроса.
3. Над данными, которые участвуют в условиях сравнения желательно не делать никаких операций — это позволяет для них использовать индексы, иначе они игнорируются.
1. Выполняя любые сравнения, приводить все данные к одному типу.
2. Если один операнд имеет значение типа TIMESTAMP или DATETIME, а другой является константой, операнды сравниваются как значения типа TIMESTAMP. А это значит, что если была строка в виде ’2008-08-14′, то она автоматически преобразуется в TIMESTAMP ’2008-08-14 00:00:00′ и это влияет на результат запроса.
3. Над данными, которые участвуют в условиях сравнения желательно не делать никаких операций — это позволяет для них использовать индексы, иначе они игнорируются.
Примеры запросов с BETWEEN и без него:
| 
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
20 
21 
22 
23 
24 
25 
26 
27 
28 
29 
30 
31 
32 
33 | # Поле 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* FROMnews  WHEREDATE(created_at) BETWEEN'2008-08-14'AND'2008-08-23';# 2: Оператор BETWEENне используем, но тоже не самый лучший вариант, индексы не используютсяSELECT* FROMnews  WHEREDATE(created_at) >= '2008-08-14'ANDDATE(created_at) <= '2008-08-23';# 3: Строки '2008-08-14 00:00:00'и '2008-08-23 23:59:59'не приведены к типу данных DATESELECT* FROMnews  WHEREcreated_at BETWEEN'2008-08-14 00:00:00'AND'2008-08-23 23:59:59';# 4: Самый лучший вариант, привели к типу DATETIME, индексы будут использоватьсяSELECT* FROMnews  WHEREcreated_at BETWEENSTR_TO_DATE('2008-08-14 00:00:00', '%Y-%m-%d %H:%i:%s')   ANDSTR_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* FROMnews   WHEREcreated_at >= '2008-08-14'ANDcreated_at <= '2008-08-23';# 6: Аналогично запросу 5SELECT* FROMnews   WHEREcreated_at BETWEENSTR_TO_DATE('2008-08-14', '%Y-%m-%d') ANDSTR_TO_DATE('2008-08-23', '%Y-%m-%d'); | 
Получаем самый лучший запрос:
| 
1 
2 
3 | SELECT* FROMnews  WHEREcreated_at BETWEENSTR_TO_DATE('2008-08-14 00:00:00', '%Y-%m-%d %H:%i:%s')   ANDSTR_TO_DATE('2008-08-23 23:59:59', '%Y-%m-%d %H:%i:%s'); |