¿Cuál es la forma óptima de comparar fechas en Microsoft SQL server?
Tengo un campo SQL datetime
en una tabla muy grande. Está indexado y necesita ser consultado.
El problema es que SQL siempre almacena el componente time (aunque siempre es medianoche), pero las búsquedas son para el día, en lugar de la hora.
declare @dateVar datetime = '2013-03-11;
select t.[DateColumn]
from MyTable t
where t.[DateColumn] = dateVar;
No devuelve nada, ya que el t.[DateColumn]
siempre incluye un componente de tiempo.
Mi pregunta es ¿cuál es la mejor manera de evitar esto?
Parece que hay dos grupos principales de opciones:
Crear un segundo variable usando
dateadd
y use unbetween ... and
o>= ... and ... <=
.Convierta el
t.[DateColumn]
en un componente de solo fecha-creo que esto hará que cualquier índice sea ignorado.
Ambos parecen muy desordenados - realmente no quiero hacer una comparación de rango o escanear la tabla.
Hay una manera mejor?
Si una de estas opciones es consistentemente manera óptima entonces cómo y por qué?
4 answers
Convertir a un DATE
o usar un rango de fechas abierto en cualquier caso dará el mejor rendimiento. Para su información, convertir a la fecha utilizando un índice son los mejores resultados. Más probando diferentes técnicas en el artículo: ¿Cuál es la forma más eficiente de recortar el tiempo de datetime? Publicado por Aaron Bertrand
De ese artículo:
DECLARE @dateVar datetime = '19700204';
-- Quickest when there is an index on t.[DateColumn],
-- because CONVERT can still use the index.
SELECT t.[DateColumn]
FROM MyTable t
WHERE = CONVERT(DATE, t.[DateColumn]) = CONVERT(DATE, @dateVar);
-- Quicker when there is no index on t.[DateColumn]
DECLARE @dateEnd datetime = DATEADD(DAY, 1, @dateVar);
SELECT t.[DateColumn]
FROM MyTable t
WHERE t.[DateColumn] >= @dateVar AND
t.[DateColumn] < @dateEnd;
También de ese artículo: usando BETWEEN
, DATEDIFF
o CONVERT(CHAR(8)...
son todos más lentos.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-03-12 12:03:07
Aquí hay un ejemplo:
Tengo una tabla de pedidos con un campo DateTime llamado OrderDate. Quiero recuperar todas las órdenes donde la fecha de la orden es igual a 01/01/2006. hay siguientes maneras de hacerlo:
1) WHERE DateDiff(dd, OrderDate, '01/01/2006') = 0
2) WHERE Convert(varchar(20), OrderDate, 101) = '01/01/2006'
3) WHERE Year(OrderDate) = 2006 AND Month(OrderDate) = 1 and Day(OrderDate)=1
4) WHERE OrderDate LIKE '01/01/2006%'
5) WHERE OrderDate >= '01/01/2006' AND OrderDate < '01/02/2006'
Se encuentra aquí
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-03-11 17:25:44
Puede agregar una columna calculada que incluya solo la fecha sin la hora. Entre las dos opciones, iría con el operador BETWEEN
porque es 'más limpio' para mí y debería hacer un mejor uso de los índices. Comparar los planes de ejecución parecería indicar que BETWEEN
sería más rápido; sin embargo, en las pruebas reales realizaron lo mismo.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-03-11 21:52:31
Obtiene elementos cuando la fecha está entre fromdate y toDate.
Donde convert (date, fromdate, 103 ) = '2016-07-26'
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-07-26 06:50:43