Heredé una gran base de datos (SQLServer) con cientos de columnas que representan cantidades de una cosa u otra. Las unidades para estos valores (por ejemplo, "galones", "pulgadas", etc.) se almacenan en el campo Descripción MS_ de Propiedades extendidas. Me pregunto si hay una mejor manera de almacenar esta información. Supongo que está bien para fines de documentación, pero sería difícil hacer cálculos sólidos de conversión de unidades basados en estos datos. En este momento no estoy preparado para hacer un cambio invasivo, pero si tengo la oportunidad de hacerlo, ¿cuál es la mejor práctica recomendada a este respecto? Las opciones, fuera de mi alcance, pueden incluir:
- Cambie el nombre de la columna a las unidades incluidas (por ejemplo, "TotalVolumeInGallons". Esto haría que la información esté un poco más disponible, pero aún me parece débil).
- Agregue una columna de "Unidades" separada para corresponder a cada columna de "Cantidad" (esta columna podría ser nvarchar O podría ser una clave foránea para una tabla de Unidades separada que podría facilitar el cálculo de las conversiones de unidades. Por otro lado, agregar muchas columnas podrían duplicar bastante el tamaño de mi base de datos, con datos terriblemente redundantes).
- Cree un nuevo campo en Propiedades extendidas dedicado específicamente para unidades. (Desafortunadamente, no creo que esto pueda ser una clave foránea para una tabla de Unidades).
- ¿Hay otra idea que estoy pasando por alto?
ACTUALIZACIÓN: Después de leer la respuesta de @Todd Everett, se me ocurrió una posible solución, así que voy a seguir adelante y responder mi propia pregunta. (Vea abajo)
Respuestas:
Como mencionas cientos de columnas, consideraría un diseño EAV . Mientras que Joe Celko advierte contra esto , creo que puede ser aplicable en su caso de uso. Parece que todas sus "cantidades" son números, por lo que evitaría los problemas de conversión que describe Joe y la necesidad de convertir cada "valor" en una cadena. Funcionará aún mejor si todas las cantidades son números enteros, pero también puede funcionar si algunas son decimales. Dadas las Unidades de medida, podría ir un paso más allá e implementar un modelo de estilo de "modelo de datos universal" basado en este artículo de David Hay y también descrito en su libro Patrones de modelo de datos: Convenciones de pensamiento . Este modelo tiene la ventaja adicional de configurar qué "cantidades" se aplican a qué "cosas" si lo necesita. Un paso adicional que se muestra en el libro de la página 162 es una tabla de conversión de unidades de medida que puede utilizar para convertir entre las diferentes unidades de medida. Aquí hay un ejemplo:
Esto dice que para convertir de Kg a Lb, el primer paso es multiplicar Kg por 2.2. También hay una constante si una conversión también debe incluir un valor constante y la capacidad de crear múltiples pasos. Entonces, al convertir, digamos Celsius a Fahrenheit, multiplique Celsius por 1.8 y luego agregue 32. La clave sería de UOM, a UOM y el Paso de cálculo.
Ese es mi valor de 2 centavos. Espero que estas referencias le den una buena idea para pensar si alguna vez tiene la oportunidad de reiniciar el diseño actual.
fuente
Todo el trabajo.
Tenga en cuenta que en el segundo caso, no puede agregar manzanas y naranjas, por lo que los datos son excepcionalmente fáciles de someter a malas interpretaciones.
También tenga en cuenta que las conversiones no pueden ser muy seguras y son susceptibles a errores de redondeo, desbordamientos, etc.
Además, hay problemas físicos como la gravedad específica y la temperatura. Convertir 20 galones de agua en libras requeriría que conozca la densidad del agua. Pero la densidad del agua cambia con la temperatura, por lo que es posible que necesite conocer la densidad contemporánea a la medición o la temperatura de manera similar y usar un factor de corrección de volumen.
En el caso de las propiedades extendidas, eso solo es bueno para la documentación; un buen nombre de columna es mejor para la documentación. El problema con la columna implicada como estar en una unidad fija por nombre es que terminas arrinconándote cuando cambias las unidades de medida (el nuevo cliente quiere petróleo en barriles y no galones) y eso estaría bien ya que sus datos están en su propia base de datos, pero el nombre de la columna ahora es engañoso.
Otra opción es almacenar versiones canónicas en unidades fijas (es decir, siempre kilogramos y metros) además de las medidas originales variables. Las operaciones agregadas en las unidades fijas deberían estar bien (excepto que no agregaría temperaturas, por ejemplo), pero no pierde la medida original.
fuente
Una solución simple que me ha funcionado bien en el pasado es almacenar todos sus datos en las unidades 'base'. Por ejemplo, su unidad base para longitudes puede ser milímetros y su unidad base para pesas puede ser kilogramos. Esta solución puede resultar en la necesidad de convertir algunos de sus datos existentes en la unidad base, si aún no lo ha hecho.
Una vez que tenga todos los datos en las unidades base estándar, no es necesario almacenar la unidad en la base de datos, ya que ahora es una suposición de todo el sistema. Las unidades que se muestran para cada tipo de unidad (por ejemplo, si se deben mostrar mm, pulgadas, cm, m de longitud) se convierten en un problema de dominio de aplicación / cliente, que se puede guardar en el almacenamiento local.
Las tablas de conversión de unidades para convertir entre las distintas unidades compatibles se pueden codificar dentro de su aplicación, ya que las nuevas unidades de medida cambian muy raramente.
Nota: una solución relacionada a otro problema es que cuando se almacenan marcas de tiempo en una base de datos para almacenarlas siempre en la unidad 'base' - UTC .
Otra Q&A relacionada sobre el tema ...
/programming/12977021/best-practice-for-storing-weights-in-a-sql-database
Contiene buena información sobre por qué utilizar un tipo de columna de coma flotante es la mejor manera de almacenar mediciones del mundo real.
fuente
Como cualquier unidad se puede convertir a otra unidad del mismo tipo con la fórmula:
Crearía una tabla que contiene los tipos de unidades más estos 4 valores.
Después de haber agregado todas las mediciones que es probable que convierta ay desde cada lado de la lista, ejecute una Consulta donde inserte la operación inversa simplemente negando los desplazamientos e intercambiando el multiplicando y el denominador y la Unidad To y From Unit.
Para agregar la conversión entre todos los tipos, una unión cruzada con algunos filtros puede insertar las conversiones de reasignación.
fuente
Después de leer la respuesta de @Todd Everett, se me ocurrió una solución, así que voy a seguir adelante y responder mi propia pregunta. Lo que creo que voy a hacer es crear una separada
ColumnUnits
mesa, con cuatro columnas:Schema
,Table
,Column
,UnitsID
(donde UnitsID es FK a una separadaUnitsOfMeasure
de mesa), la cartografía de este modo cualquier columna dada a su Unidad de medida asociado. Obviamente, el mayor inconveniente de esta idea es que los desarrolladores tendrían que recordar editar esta tabla cada vez que cambien el nombre de una columna o tabla [¿ quizás usen un disparador DDL ?], de lo contrario el sistema se romperá. Pero suponiendo que tales cambios de nombre sean raros, y que la tienda de desarrollo sea pequeña (solo una persona, en mi caso), esta arquitectura debería ser viable. La ventaja es que no se deben realizar cambios invasivos en la base de datos actual, y solo tengo que almacenar el valor una vez para cada columna, en lugar de una vez por fila, como lo requeriría mi segunda opción en mi publicación original.fuente