MySQL SELECCIONA DONDE la fecha y hora coincide con el día (y no necesariamente la hora)

127

Tengo una tabla que contiene una columna de fecha y hora. Deseo devolver todos los registros de un día determinado, independientemente de la hora. O, en otras palabras, si mi tabla solo contuviera los siguientes 4 registros, solo se devolverían el segundo y el tercero si me limito al 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
usuario1032531
fuente
Vea la respuesta de John Woo en stackoverflow.com/questions/14769026/…
ekerner el

Respuestas:

326

NUNCA use un selector como DATE(datecolumns) = '2012-12-24': es un asesino de rendimiento:

  • calculará DATE()para todas las filas, incluidas aquellas que no coinciden
  • hará que sea imposible usar un índice para la consulta

Es mucho más rápido de usar

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

ya que esto permitirá el uso del índice sin cálculo.

EDITAR

Como señaló Used_By_Already, en el tiempo transcurrido desde la respuesta inicial en 2012, han surgido versiones de MySQL, donde usar '23: 59: 59 'como fin de día ya no es seguro. Una versión actualizada debería leer

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

La esencia de la respuesta, es decir, la evitación de un selector en una expresión calculada, por supuesto, sigue en pie.

Eugen Rieck
fuente
Estaba a punto de comentar que la solución de a1ex07 no parece tan buena como las otras. Después de leer tu publicación, ¡tal vez necesito revertir mi pensamiento!
user1032531
2
Recién probado en dos servidores, lo anterior es MUCHO (10 veces al menos) más rápido que date () = '' especialmente para tablas enormes. Gracias
zzapper
1
@KonradViltersten Utilicé una forma muy detallada de formular la consulta para hacerla más legible y llevar mi punto a casa, sin refinarlo. La respuesta de a1ex07 tiene la sintaxis dispersa.
Eugen Rieck
9
@KonradViltersten - Mejor aún: WHERE col >= '2012-12-25' AND col < '2012-12-25' + INTERVAL 1 DAY. Evita el tiempo 0 y trabaja para DATE, DATETIME, DATETIME(6), etc, y se ocupa de salto días, etc.
Rick James
1
'2012-12-25 23:59:59' NO ES VÁLIDO como un final del día, siempre fue una mala idea y causará errores en las versiones de MySQL que admiten una precisión inferior al segundo. Mucho mejor usar el enfoque de Rick James (arriba) o a1ex07 (otra respuesta)
Used_By_Already
34

... WHERE date_column >='2012-12-25' AND date_column <'2012-12-26'potencialmente puede funcionar mejor (si tiene un índice en date_column) que DATE.

a1ex07
fuente
1
De hecho, me pregunto qué es más rápido: esta o la BETWEENsolución ... ¿alguien se sorprendió?
jave.web
66
No debería haber ninguna diferencia. BETWEENEs solo una forma de escribir field >= value1 and fied<= value2.
a1ex07
1
Tenga en cuenta que según el Manual de MySQL: "Para obtener los mejores resultados al usar ENTRE valores de fecha u hora, use CAST () para convertir explícitamente los valores al tipo de datos deseado. Ejemplos: si compara un DATETIME con dos valores DATE, convierta el DATE valores a DATETIME. Si utiliza una constante de cadena como '2001-1-1' en comparación con una FECHA, convierta la cadena a una FECHA ". Por lo tanto, a menos que todos sean del mismo tipo, es mejor lanzarlos explícitamente.
techdude
21

Puedes usar %:

SELECT * FROM datetable WHERE datecol LIKE '2012-12-25%'
Ghilas BELHADJ
fuente
13
LIKE parece ser tan lento como DATE (datetimecol). Mejor use la solución de Eugen o a1ex07.
Marie Fischer
3
No siempre se trata de velocidad. Entonces me gusta esta solución. Es mucho más legible.
Simon Hansen el