Nota: Cuando escribí originalmente esta respuesta me dijeron que un índice en una de las columnas podría crear una consulta que se comporta mejor que otras respuestas (y mencionado Dan Fuller). Sin embargo, no estaba pensando 100% correctamente. El hecho es que, sin una columna calculada o vista indexada (materializada), una exploración de tabla completa va a ser requerida, porque las dos columnas de fecha que se comparan son de la misma tabla !
Creo que todavía hay valor en la información a continuación, a saber 1) la posibilidad de un mejor rendimiento en la situación correcta, cuando la comparación es entre columnas de diferentes tablas, y 2) promover el hábito en los desarrolladores SQL de las mejores prácticas y remodelar su pensamiento en la dirección correcta.
Haciendo Condiciones sargable
La mejor práctica que me refiero es uno de mover una columna a estar solo en un lado del operador de comparación, así:
SELECT InitialSave = DateDiff(second, T.BegTime, T.EndTime)
FROM dbo.MyTable T
WHERE T.EndTime <= T.BegTime + '00:00:10'
Mientras dijo, esto no evitará una exploración en una sola tabla, sin embargo, en una situación como esta podría hacer una gran diferencia:
SELECT InitialSave = DateDiff(second, T.BegTime, T.EndTime)
FROM
dbo.BeginTime B
INNER JOIN dbo.EndTime E
ON B.BeginTime <= E.EndTime
AND B.BeginTime + '00:00:10' > E.EndTime
EndTime
está en ambas condiciones ahora solo en un lado de la comparación.Suponiendo que la tabla BeginTime
tiene muchas menos filas, y la mesa EndTime
tiene un índice en la columna EndTime
, esto llevará a cabo mucho, mucho mejor que cualquier cosa usando DateDiff(second, B.BeginTime, E.EndTime)
. Es ahora sargable, lo que significa que hay un "argumento de búsqueda" válido - así como el motor exploracionesBeginTime
la tabla, se pueden buscar en la tabla EndTime
. La selección cuidadosa de los cuales la columna es de por sí se requiere en un lado del operador - que puede ser vale la pena experimentar poniendo BeginTime
por sí mismo haciendo algo de álgebra para cambiar a AND B.BeginTime > E.EndTime - '00:00:10'
precisión de DifFecha
I también debería señalar que DateDiff
no vuelve transcurrido el tiempo, sino que cuenta el número de límites cruzados. Si una llamada a DateDiff
utilizando segundos vuelve 1
, esto podría significar 3 ms
tiempo transcurrido, o podría significar 1997 ms
! Esto es esencialmente una precisión de + - 1 unidades de tiempo. Para la mejor precisión de + - 1/2 unidad de tiempo, le gustaría que la siguiente consulta comparando 0
-EndTime - BegTime
:
SELECT DateDiff(second, 0, EndTime - BegTime) AS InitialSave
FROM MyTable
WHERE EndTime <= BegTime + '00:00:10'
Esto ahora tiene un error máximo redondeo de sólo un segundo conjunto, no dos (en efecto, una operación de piso()). Tenga en cuenta que solo puede restar el tipo de datos datetime
- para restar un valor de date
o time
que debe convertir a datetime
o utilizar otros métodos para obtener la mejor precisión (un lote de DateAdd
, DateDiff
y posiblemente otra basura, o quizás usando una unidad de tiempo de mayor precisión y división).
Este principio es especialmente importante cuando contar unidades más grandes, tales como horas, días o meses. Un DateDiff
de 1 month
podría tener 62 días de diferencia (1 de julio de pensar, 2013 - Aug 31 2013)!
Entonces, si estoy seleccionando 20 columnas además de esto, tendré que SELECCIONARlas en ambas declaraciones (interna y externa), ¿correcto? ¿Hay una mejor manera? –
Si lo desea, puede usar select * en la primera línea, en lugar de seleccionar InitialSave, Col2, Col3, etc. –
¡Oh, duh! ¡Gracias! * se da palmadas en la cabeza * –