¿Qué método proporciona el mejor rendimiento al eliminar la porción de tiempo de un campo de fecha y hora en SQL Server?
a) select DATEADD(dd, DATEDIFF(dd, 0, getdate()), 0)
o
b) select cast(convert(char(11), getdate(), 113) as datetime)
El segundo método envía algunos bytes más de cualquier manera, pero eso podría no ser tan importante como la velocidad de la conversión.
Ambos también parecen ser muy rápidos, pero ¿puede haber una diferencia en la velocidad cuando se trata de cientos de miles o más filas?
Además, ¿es posible que existan métodos aún mejores para deshacerse de la porción de tiempo de una fecha y hora en SQL?
Respuestas:
Estrictamente, el método
a
es el que menos recursos requiere:Probó menos CPU intensiva para la misma duración total, un millón de filas por alguien con demasiado tiempo en sus manos: ¿ La forma más eficiente en SQL Server para obtener la fecha de la fecha y la hora?
Vi una prueba similar en otro lugar con resultados similares también.
Prefiero el DATEADD / DATEDIFF porque:
Ejemplo: ¿Por qué mi expresión CASE no es determinista?
Editar, oct 2011
Para SQL Server 2008+, puede CAST a
date
ieCAST(getdate() AS date)
. O simplemente use eldate
tipo de datos para no tener tiempo de eliminar.Edit, ene 2012
Un ejemplo práctico de lo flexible que es esto: es necesario calcular por hora redondeada o cifra de fecha en el servidor SQL
Editar, mayo de 2012
No use esto en las cláusulas WHERE y similares sin pensar: agregar una función o CAST a una columna invalida el uso del índice. Vea el número 2 aquí: http://www.simple-talk.com/sql/t-sql-programming/ten-common-sql-programming-mistakes/
Ahora, esto tiene un ejemplo de versiones posteriores del optimizador de SQL Server que administran CAST hasta la fecha correctamente, pero en general será una mala idea ...
Editar, septiembre de 2018, para datetime2
fuente
DATE
tiempo de datos es desagradablemente restrictivo en lo que le permitirá hacer con respecto a cosas como dateadd, dateiff e interactuar con otros tipos de datos de fecha / hora. Para esos casos, elDATEADD()
enfoque reina el rey.0218
lugar de2018
como el año y laDATEDIFF
parte de su declaración arroja una excepción.The conversion of a datetime2 data type to a datetime data type resulted in an out-of-range datetime value
Intente:select DATEDIFF(dd, 0, convert(datetime2(0), '0218-09-12', 120))
SELECT DATEDIFF(dd, '19000101', convert(datetime2(0), '0218-09-12', 120))
En SQL Server 2008, puede usar:
fuente
datetime
adate
, por lo que su solución se reduce a soloCONVERT(DATE,getdate())
, lo que ya se ha sugerido más de una vez.CAST(GETDATE() AS DATE)
o estrictamente ANSI,CAST(CURRENT_TIMESTAMP AS DATE)
que creo que no tiene valor. Quédate con el primero.Por supuesto, este es un hilo viejo, pero para completarlo.
Desde SQL 2008 puede usar el tipo de datos DATE para que simplemente pueda hacer:
fuente
... no es una buena solución, según los comentarios a continuación.
Eliminaría esta respuesta, pero la dejaré aquí como contraejemplo, ya que creo que la explicación de los comentaristas de por qué no es una buena idea sigue siendo útil.
fuente
En SQL Server 2008, hay un tipo de fecha FECHA (también un tipo de datos HORA).
o
fuente
Aquí hay otra respuesta, de otra pregunta duplicada:
Este método de número mágico funciona un poco más rápido que el método DATEADD. (Parece que ~ 10%)
El tiempo de CPU en varias rondas de un millón de registros:
Pero tenga en cuenta que estos números son posiblemente irrelevantes porque ya son MUY rápidos. A menos que tuviera conjuntos de registros de 100,000 o más, ni siquiera podría obtener el tiempo de CPU para leer por encima de cero.
Teniendo en cuenta el hecho de que DateAdd está destinado a este propósito y es más robusto, yo diría que use DateAdd.
fuente
'12:00:00.003'
embargo, su respuesta ofrece la posibilidad de usar lo que creo que es mucho mejor.fuente
De verdad me gusta:
El
120
código de formato forzará la fecha en el estándar ISO 8601:¡Súper fácil de usar en dplyr (
R
) y pandas (Python
)!fuente
¡TENER CUIDADO!
¡El método a) yb) NO siempre tiene la misma salida!
Salida:
2014-01-01 00:00:00.000
Salida:
2013-12-31 00:00:00.000
(Probado en MS SQL Server 2005 y 2008 R2)
EDITAR: Según el comentario de Adam, esto no puede suceder si lee el valor de la fecha de la tabla, pero puede suceder si proporciona su valor de la fecha como un literal (ejemplo: como un parámetro de un procedimiento almacenado llamado a través de ADO.NET).
fuente
DATETIME
columna. El más alto disponible es .997 De: msdn.microsoft.com/en-us/library/ms187819.aspx verá que los valores se redondean para tener el lugar número mil a 0, 3 o 7. El OP no verá El valor de su prueba en sus tablas.Franja de tiempo en inserciones / actualizaciones en primer lugar. En cuanto a la conversión sobre la marcha, nada puede vencer a una función definida por el usuario en cuanto al mantenimiento:
La implementación de
date_only
puede ser lo que quieras: ahora se abstrae y el código de llamada es mucho más limpio.fuente
WHERE DateAdd(DateDiff(Column)) = @DateValue
No usará un índice. Por otro lado,WHERE Column >= dbo.UDF(@DateValue) AND Column < dbo.UDF(@DateValue + 1)
es SARGable. Así que ten cuidado de cómo lo pones.Vea esta pregunta:
¿Cómo puedo truncar una fecha y hora en SQL Server?
Hagas lo que hagas, no uses el método de cadena . Esa es la peor forma en que puedes hacerlo.
fuente
Ya respondí, pero también tiraré esto por ahí ... supuestamente también se realiza bien, pero funciona al tirar el decimal (que almacena el tiempo) del flotador y devolver solo una parte completa (que es la fecha)
la segunda vez que encontré esta solución ... tomé este código
fuente
Este método no utiliza la función de cadena.
Date
es básicamente un tipo de datos real con dígitos antes de decimales que son fracción de un día.Creo que esto será más rápido que muchos.
fuente
Para mí, el siguiente código siempre es un ganador:
fuente
seleccione CONVERTIR (char (10), GetDate (), 126)
fuente
Creo que quieres decir
cast(floor(cast(getdate()as float))as datetime)
real solo tiene 32 bits y podría perder algo de información
Esto es más rápido
cast(cast(getdate()+x-0.5 as int)as datetime)
... aunque solo un 10% más rápido
(about 0.49 microseconds CPU vs. 0.58)
Esto fue recomendado y toma el mismo tiempo en mi prueba en este momento:
DATEADD(dd, DATEDIFF(dd, 0, getdate()), 0)
En SQL 2008, la función CLR de SQL es aproximadamente 5 veces más rápida de lo que sería usar una función de SQL, a 1,35 microsegundos frente a 6,5 microsecciones, lo que indica una sobrecarga de llamadas de función mucho menor para una función CLR de SQL frente a una simple UDF de SQL.
En SQL 2005, la función CLR de SQL es 16 veces más rápida, según mis pruebas, en comparación con esta función lenta:
fuente
¿Qué tal
select cast(cast my_datetime_field as date) as datetime)
? Esto da como resultado la misma fecha, con la hora establecida en 00:00, pero evita cualquier conversión a texto y también evita cualquier redondeo numérico explícito.fuente
Creo que si sigues estrictamente con
TSQL
esto, esta es la forma más rápida de truncar el tiempo:Encontré que este método de truncamiento es aproximadamente un 5% más rápido que el
DateAdd
método. Y esto se puede modificar fácilmente para redondear al día más cercano de esta manera:fuente
Aquí hice una función para eliminar algunas partes de una fecha y hora para SQL Server. Uso:
create function dbo.uf_RoundDateTime(@dt as datetime, @part as char) returns datetime as begin if CHARINDEX( @part, 'smhd',0) = 0 return @dt; return cast( Case @part when 's' then convert(varchar(19), @dt, 126) when 'm' then convert(varchar(17), @dt, 126) + '00' when 'h' then convert(varchar(14), @dt, 126) + '00:00' when 'd' then convert(varchar(14), @dt, 112) end as datetime ) end
fuente
En caso de que alguien esté buscando una versión de Sybase ya que varias de las versiones anteriores no funcionaron
fuente
cast
: para SQL Server 2008+, puede CAST hasta la fecha. O simplemente use la fecha para no tener tiempo para eliminar.datetime
adate
: ninguno de los dos tiene un formato inherente.Si es posible, para cosas especiales como esta, me gusta usar las funciones CLR.
En este caso:
fuente
Yo, personalmente, casi siempre uso funciones definidas por el usuario por el para esto si se trata de SQL Server 2005 (o una versión inferior), sin embargo, debe tenerse en cuenta que existen inconvenientes específicos para usar UDF, especialmente si se aplican a las cláusulas WHERE (ver más abajo y los comentarios sobre esta respuesta para más detalles). Si usa SQL Server 2008 (o superior), consulte a continuación.
De hecho, para la mayoría de las bases de datos que creo, agrego estos UDF justo al comienzo, ya que sé que hay un 99% de posibilidades de que los necesite tarde o temprano.
Creo uno para "solo fecha" y "solo hora" (aunque el "solo fecha" es, con mucho, el más usado de los dos).
Aquí hay algunos enlaces a una variedad de UDF relacionados con la fecha:
Funciones esenciales de fecha, hora y fecha y hora de SQL Server
Obtener función solo de fecha
El último enlace muestra no menos de 3 formas diferentes de obtener la fecha solo como parte de un campo de fecha y hora y menciona algunos pros y contras de cada enfoque.
Si usa un UDF, debe tenerse en cuenta que debe intentar evitar usar el UDF como parte de una cláusula WHERE en una consulta, ya que esto dificultará en gran medida el rendimiento de la consulta. La razón principal de esto es que el uso de un UDF en una cláusula WHERE hace que esa cláusula sea no sargable , lo que significa que SQL Server ya no puede usar un índice con esa cláusula para mejorar la velocidad de ejecución de la consulta. Con referencia a mi propio uso de UDF, usaré con frecuencia la columna de fecha "sin procesar" dentro de la cláusula WHERE, pero aplicaré el UDF a la columna SELECTed. De esta forma, el UDF solo se aplica al conjunto de resultados filtrado y no a todas las filas de la tabla como parte del filtro.
Por supuesto, el mejor enfoque absoluto para esto es usar SQL Server 2008 (o superior) y separar sus fechas y horas , ya que el motor de base de datos de SQL Server proporciona de forma nativa los componentes de fecha y hora individuales, y puede consultarlos de manera eficiente de forma independiente sin la necesidad de un UDF u otro mecanismo para extraer la parte de fecha u hora de un tipo de fecha y hora compuesto.
fuente
WHERE DateColumn >= {TimeTruncatingExpression}(@DateValue) AND DateColumn < {TimeTruncatingExpression}(@DateValue + 1)
. Sentí que tenía que decir algo, ya que usted dijo que "casi siempre uso UDF" no explicaba ninguno de los inconvenientes, ni la forma de hacer una consulta de fecha única SARGable.Yo usaría:
Por lo tanto, crear efectivamente un nuevo campo desde el campo de fecha que ya tiene
fuente
datetime
valor, convertirlos en cadenas, concatenarlos juntos y finalmente convertir el resultado nuevamentedatetime
es mejor que, por ejemplo, realizar cálculos directos en el originaldatetime
(el métodoDATEADD
/DATEDIFF
)?MM
yDD
? No hay tales funciones en SQL Server.