¿Cómo puedo truncar una fecha y hora en SQL Server?
¿Cuál es la mejor manera de truncar un valor de fecha y hora (para eliminar horas, minutos y segundos) en SQL Server?
Por ejemplo:
declare @SomeDate datetime = '2009-05-28 16:30:22'
select trunc_date(@SomeDate)
-----------------------
2009-05-28 00:00:00.000
Esto continúa reuniendo votos adicionales con frecuencia, incluso varios años después, por lo que necesito actualizarlo para las versiones modernas de Sql Server. Para Sql Server 2008 y posteriores, es sencillo:
cast(getdate() as Date)
Tenga en cuenta que los últimos tres párrafos cerca del final todavía se aplican y, a menudo, es necesario dar un paso atrás y encontrar una manera de evitar el yeso en primer lugar.
Pero también hay otras formas de lograrlo. Aquí están los más comunes.
La forma correcta (nueva desde Sql Server 2008)
cast(getdate() as Date)
La forma correcta (antigua)
dateadd(dd, datediff(dd, 0, getdate()), 0)
Esto es más antiguo ahora, pero aún vale la pena saberlo porque también puede adaptarse fácilmente a otros momentos, como el primer momento del mes, minuto, hora o año.
Esta forma correcta utiliza funciones documentadas que forman parte del estándar ANSI y cuyo funcionamiento está garantizado, pero puede ser algo más lento. Funciona encontrando cuántos días hay desde el día 0 hasta el día actual y sumando esa cantidad de días al día 0. Funcionará sin importar cómo esté datetime
almacenado y sin importar cuál sea su ubicación.
la manera rapida
cast(floor(cast(getdate() as float)) as datetime)
Esto funciona porque datetime
las columnas se almacenan como valores binarios de 8 bytes. Transmítelos a float
, floor
para eliminar la fracción y la parte de tiempo de los valores desaparecerá cuando los vuelva a transmitir a datetime
. Todo cambia un poco sin una lógica complicada y es muy rápido.
Tenga en cuenta que esto depende de un detalle de implementación que Microsoft puede cambiar en cualquier momento, incluso en una actualización automática del servicio. Tampoco es muy portátil. En la práctica, es muy poco probable que esta implementación cambie pronto, pero aún así es importante ser consciente del peligro si decide utilizarla. Y ahora que tenemos la opción de elegir una fecha, rara vez es necesario.
La forma incorrecta
cast(convert(char(11), getdate(), 113) as datetime)
La forma incorrecta funciona al convertir a una cadena, truncar la cadena y volver a convertirla a una fecha y hora. Está mal por dos razones:
- Es posible que no funcione en todas las configuraciones regionales y
- Se trata de la forma más lenta posible de hacer esto... y no sólo un poco; es como uno o dos órdenes de magnitud más lento que las otras opciones.
Actualización Esto ha recibido algunos votos últimamente, por lo que quiero agregar que desde que publiqué esto he visto evidencia bastante sólida de que Sql Server optimizará la diferencia de rendimiento entre la forma "correcta" y la forma "rápida". , lo que significa que ahora deberías favorecer lo primero.
En cualquier caso, desea escribir sus consultas para evitar la necesidad de hacerlo en primer lugar. Es muy raro que debas hacer este trabajo en la base de datos.
En la mayoría de los lugares, la base de datos ya es un cuello de botella. Generalmente, es el servidor al que resulta más costoso agregar hardware para mejorar el rendimiento y el más difícil de lograr esas adiciones correctamente (hay que equilibrar los discos con la memoria, por ejemplo). También es el más difícil de escalar hacia afuera, tanto desde el punto de vista técnico como empresarial; Técnicamente es mucho más fácil agregar un servidor web o de aplicaciones que un servidor de base de datos e incluso si eso fuera falso, no paga más de $20,000 por licencia de servidor para IIS o Apache.
Lo que intento señalar es que, siempre que sea posible, debes hacer este trabajo a nivel de aplicación. El único momento en el que debería encontrarse truncando un datetime
servidor Sql es cuando necesita agrupar por día, e incluso entonces probablemente debería tener una columna adicional configurada como una columna calculada, mantenida en el momento de inserción/actualización, o mantenida en lógica de aplicación. Elimine este trabajo que rompe índices y consume mucha CPU de su base de datos.
Sólo para SQL Server 2008
CAST(@SomeDateTime AS Date)
Luego, vuelve a enviarlo a la fecha y hora si quieres.
CAST(CAST(@SomeDateTime AS Date) As datetime)
Solo en aras de una respuesta más completa, aquí hay una forma funcional de truncar a cualquiera de las partes de la fecha e incluir minutos (reemplace GETDATE()
con la fecha para truncar).
Esto es diferente de la respuesta aceptada en que puede usar no solo dd
(días), sino también cualquiera de las partes de la fecha (ver aquí ):
dateadd(minute, datediff(minute, 0, GETDATE()), 0)
Tenga en cuenta que en la expresión anterior, 0
es una fecha constante al comienzo de un año (1900-01-01). Si necesita truncar a partes más pequeñas, como segundos o milisegundos, debe tomar una fecha constante que esté más cerca de la fecha que se va a truncar para evitar un desbordamiento.
El fragmento que encontré en la web cuando tuve que hacer esto fue:
dateadd(dd,0, datediff(dd,0, YOURDATE))
e.g.
dateadd(dd,0, datediff(dd,0, getDate()))
CONVERT(DATE, <yourdatetime>) or CONVERT(DATE, GetDate()) or CONVERT(DATE, CURRENT_TIMESTAMP)