Podemos almacenar información de fecha y hora de dos maneras. ¿Cuál es el mejor enfoque para almacenar información de fecha y hora?
¿Almacenar fecha y hora en 2 columnas separadas o una columna usando DateTime ?
¿Puedes explicar por qué ese enfoque es mejor?
(Enlace a documentos de MySQL para referencia, la pregunta es general, no específica de MySQL)
Tipos de fecha y hora : fecha y hora
database-design
datetime
Julian
fuente
fuente
date,time
congroup by date
, pero no para un índice endatetime
congroup by cast(datetime as date)
pesar de que suministraría el orden deseado.Respuestas:
Almacenar los datos en una sola columna es la forma preferida, ya que están inextricablemente vinculados. Un punto en el tiempo es una sola pieza de información, no dos.
Una forma común de almacenar datos de fecha / hora, empleados "detrás de escena" por muchos productos, es convirtiéndolos en un valor decimal donde la "fecha" es la parte entera del valor decimal, y el "tiempo" es la fracción valor. Entonces, 1900-01-01 00:00:00 se almacena como 0.0 y 20 de septiembre de 2016 9:34:00 se almacena como 42631.39861. 42631 es el número de días desde 1900-01-01. .39861 es la porción de tiempo transcurrido desde la medianoche. No use un tipo decimal directamente para hacer esto, use un tipo explícito de fecha / hora; mi punto aquí es solo una ilustración.
Almacenar los datos en dos columnas separadas significa que deberá combinar los dos valores de las columnas cada vez que desee ver si un punto dado en el tiempo es anterior o posterior al valor almacenado.
Si almacena los valores por separado, invariablemente se encontrará con "errores" que son difíciles de detectar. Tome por ejemplo lo siguiente:
En el código anterior, estamos creando una tabla de prueba, rellenándola con dos valores, luego realizando una consulta simple contra esos datos. El primero
SELECT
devuelve ambas filas, sin embargo, el segundoSELECT
solo devuelve una sola fila, que puede no ser el resultado deseado:La forma correcta de filtrar un rango de fecha / hora donde los valores están en columnas discretas, como lo señala @ypercube en los comentarios, es:
Si necesita separar el componente de tiempo para fines de análisis , podría considerar agregar una columna calculada y persistente para la parte de tiempo del valor:
La columna persistente se podría indexar permitiendo clasificaciones rápidas, etc., por hora del día.
Si está considerando dividir la fecha y la hora en dos campos para fines de visualización, debe tener en cuenta que el formateo debe realizarse en el cliente, no en el servidor.
fuente
Voy a proporcionar una opinión disidente a las otras respuestas.
Si los componentes de fecha y hora se requieren juntos, es decir, una entrada no es válida si contiene uno pero no el otro (o es NULL en uno pero no en el otro), entonces almacenarlo en una sola columna tiene sentido por las razones dadas en otro respuestas
Sin embargo, puede darse el caso de que uno o ambos componentes sean individualmente opcionales. En ese caso, sería incorrecto almacenarlo en una sola columna. Hacerlo te obligaría a representar valores NULL de manera arbitraria, por ejemplo, almacenar la hora como 00:00:00.
Aquí hay un par de ejemplos:
Está registrando viajes en vehículos para deducciones de impuestos por milla. Sería útil conocer la hora exacta del viaje, pero si un empleado no lo anota y lo ha olvidado, la fecha aún debe registrarse por sí misma (fecha requerida, hora opcional).
Está realizando una encuesta para averiguar a qué hora las personas comen su almuerzo, y solicita a los participantes que completen un formulario con una muestra de sus horas de almuerzo, incluidas las fechas. Algunos no se molestan en completar la fecha, y no desea descartar los datos, ya que son las horas que realmente le importan (fecha opcional, hora requerida).
Vea esta pregunta relacionada para enfoques alternativos.
fuente
Siempre preferiré almacenar eso como una sola columna a menos que haya una demanda específica de negocios / aplicaciones. A continuación están mis puntos:
fuente
En SQL Server, es mejor almacenar DataTime como un campo. Si crea un índice en la columna DataTime, puede usarse como búsqueda de fecha y como búsqueda de fecha y hora. Por lo tanto, si necesita limitar todos los registros que existen para la fecha específica, aún puede usar el índice sin tener que hacer nada especial. Si necesita consultar la porción de tiempo, no podrá usar el mismo índice y, por lo tanto, si tiene un caso de negocios en el que le importa más la hora del día que DateTime, debe almacenarlo por separado, ya que deberá crear un índice sobre él y mejorar el rendimiento.
fuente
De hecho, es una pena que no haya un tipo de DBMS cruzado estándar para esto (como INT y VARCHAR son para enteros y valores de cadena). Los 2 enfoques de bases de datos cruzadas que he conocido hasta ahora usan columnas VARCHAR / CHAR para almacenar valores de DataTime como cadenas formateadas de acuerdo con el estándar ISO 8601 (más conveniente, legible para humanos) y BIGINT para almacenarlas como marcas de tiempo POSIX (almacenadas más eficiente, más rápido, más fácil de manipular matemáticamente).
fuente
timestamp
eso es lo que define el estándar SQL. Almacenar marcas de tiempo como cadenas es un muy mal consejoDespués de leer un montón de cosas, el tiempo UTC Unix en BIGINT parece ser la solución óptima. ID de TZDB timesone en VARCHAR para almacenamiento de zona horaria si es necesario. Algunos argumentos:
TIMESTAMP y DATETIME realizan un montón de conversiones efectivas en segundo plano que parecen ser complejas y no claras. El servidor cambia de la hora local a UTC o a la hora del servidor y viceversa, a veces o no. Un montón de gastos generales ocultos para cada función.
BIGINT (8kb) es al menos tan ligero o más ligero que DECIMAL requerido para el almacenamiento en formato xxxxxx.xxxxxx, que MySQL prácticamente almacena como dos INTs + algo . Y es suficiente para almacenar siglos por delante.
Casi todos los principales lenguajes de programación tienen bibliotecas de funciones estándar para trabajar con el tiempo Unix.
Las operaciones matemáticas con BIGINT deberían ser tan rápidas o más rápidas que cualquier otra cosa en cualquier hardware.
Por supuesto, todo lo anterior es relevante para grandes proyectos internacionales. Para algo pequeño, ir con el formato predeterminado del marco elegido parece ser lo suficientemente bueno.
fuente
timestamp
columna no se producen "conversiones efectivas" (en la capa de la base de datos) y paratimestamp with time zone
esto está bien documentado y explicado en los manuales (al menos para Oracle y Postgres)