Conversión Implícita
Supuse que el tipo de datos post_date es Datetime. Sin embargo, no importa si el tipo en el otro lado es Datetime, Datetime2 o simplemente Time porque la cadena (Varchar) se convertirá implícitamente en Datetime.
Con post_date declarado como Datetime2 (u Time), la posted_date <= '2015-07-27 23:59:59.99999'
cláusula where falla porque aunque 23:59:59.99999
es un valor válido de Datetime2, este no es un valor válido de Datetime:
Conversion failed when converting date and/or time from character string.
Rango de tiempo para fecha y hora
El rango de tiempo de Fecha y hora es de 00:00:00 a 23: 59: 59.997. Por lo tanto, 23: 59: 59.999 está fuera de rango y debe redondearse hacia arriba o hacia abajo al valor más cercano.
Exactitud
Además, los valores de fecha y hora se redondean en incrementos de .000, .003 o .007 segundos. (es decir, 000, 003, 007, 010, 013, 017, 020, ..., 997)
Este no es el caso con el valor 2015-07-27 23:59:59.999
que está dentro de este rango: 2015-07-27 23:59:59.997
y 2015-07-28 0:00:00.000
.
Este rango corresponde a las opciones anteriores y siguientes más cercanas, ambas terminando con .000, .003 o .007.
Redondeando hacia arriba o hacia abajo ?
Debido a que es más cercano a 2015-07-28 0:00:00.000
(1 frente a -2) que 2015-07-27 23:59:59.997
, la cadena se redondea y se convierte este valor de fecha y hora: 2015-07-28 0:00:00.000
.
Con un límite superior como 2015-07-27 23:59:59.998
(o .995, .996, .997, .998), se habría redondeado hacia abajo 2015-07-27 23:59:59.997
y su consulta habría funcionado como se esperaba. Sin embargo, no habría sido una solución sino un valor afortunado.
Datetime2 o tipos de hora
Datetime2 y rangos de tiempo de tiempo son 00:00:00.0000000
a través de 23:59:59.9999999
con una precisión de 100 ns (el último dígito, cuando se usa con una precisión de 7 dígitos).
Sin embargo, un rango de fecha y hora (3) no es similar al rango de fecha y hora:
- Datetime
0:0:00.000
a23:59:59.997
- Datetime2
0:0:00.000000000
a23:59:59.999
Solución
Al final, es más seguro buscar fechas por debajo del día siguiente que las fechas por debajo o iguales a lo que crees que es el último fragmento de la hora del día. Esto se debe principalmente a que sabe que el día siguiente siempre comienza a las 0: 00: 00,000 pero que los diferentes tipos de datos pueden no tener la misma hora al final del día:
Datetime `0:0:00.000` to `23:59:59.997`
Datetime2 `0:0:00.000000000` to `23:59:59.999-999-900`
Time2 `0:0:00.000000000` to `23:59:59.999-999-900`
< 2015-07-28 0:00:00.000
le dará resultados precisos y es la mejor opción
<= 2015-07-27 23:59:59.xxx
puede devolver valores inesperados cuando no se redondea a lo que cree que debería ser.
- Se debe evitar la conversión a la fecha y el uso de la función porque limita el uso de índices
Podríamos pensar que cambiar [date_date] a Datetime2 y su mayor precisión podría solucionar este problema, pero no ayudará porque la cadena todavía se convierte a Datetime. Sin embargo, si se agrega un elenco cast(2015-07-27 23:59:59.999' as datetime2)
, esto funciona bien
Moldear y Convertir
Cast puede convertir un valor de hasta 3 dígitos a Datetime o con hasta 9 dígitos a Datetime2 u Time y redondearlo a la precisión correcta.
Cabe señalar que Cast of Datetime2 y Time2 pueden dar resultados diferentes:
select cast('20150101 23:59:59.999999999' as datetime2(7))
es redondeado 2015-05-03 00: 00: 00.0000000 (para un valor superior a 999999949)
select cast('23:59:59.999999999' as time(7))
=> 23: 59: 59.9999999
En cierto modo, soluciona el problema que la fecha y hora tiene con los incrementos de 0, 3 y 7, aunque siempre es mejor buscar fechas antes del primer nano segundo del día siguiente (siempre 0: 00: 00.000).
Fuente MSDN: fecha y hora (Transact-SQL)
gives you control of DATE and TIME as opposed to datetime.
¿Qué significa eso?DateTime2
vsDateTime
.: a. Para la gran mayoría de los casos de uso en el mundo real , beneficios deDateTime2
Mucho <costos. Ver: stackoverflow.com/questions/1334143/… b. Ese no es el problema raíz aquí. Ver siguiente comentario.datetime3
agregan 70 (vs. 7) dígitos de precisión?). La mejor práctica es usar un valor donde la precisión no importa, es decir, <el comienzo del siguiente segundo, minuto, hora o día vs. <= el final del segundo, minuto, hora o día anterior.