¿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:

  1. Crear un segundo variable usando dateadd y use un between ... and o >= ... and ... <=.

  2. 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é?

Author: Keith, 2013-03-11

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.

 27
Author: Aleksandr Fedorenko,
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í

 10
Author: paraselena,
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.

 0
Author: Michael L.,
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'

 0
Author: gaze,
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