Tendría que rastrear los cambios en el precio de los productos para poder consultar en la base de datos el precio de un producto en una fecha determinada. La información se utiliza en un sistema que calcula auditorías históricas, por lo que debe devolver el precio correcto para el producto correcto según la fecha de compra.
Preferiría usar postgres en la construcción de la base de datos.
Necesito el diseño de la base de datos, pero todas y cada una de las sugerencias de mejores prácticas también son bienvenidas.
database-design
best-practices
Gunnar Norred
fuente
fuente
prices
crear una tablaprices_history
con columnas similares. Hibernate Envers puede automatizar esto por ustedRespuestas:
Si entiendo el escenario adecuadamente, debe definir una tabla que conserve una serie temporal de precios ; por lo tanto, estoy de acuerdo, esto tiene mucho que ver con el aspecto temporal de la base de datos con la que está trabajando.
Reglas del negocio
Comencemos analizando la situación desde el nivel conceptual. Entonces, si , en su dominio comercial,
entonces eso significa que
El diagrama IDEF1X que se muestra en la Figura 1 , aunque está muy simplificado, representa este escenario:
Diseño lógico expositivo
Y el siguiente diseño de nivel lógico SQL-DDL, basado en dicho diagrama IDEF1X, ilustra un enfoque factible que puede adaptar a sus propias necesidades exactas:
La
Price
tabla tiene una CLAVE PRIMARIA compuesta compuesta por dos columnas, es decir,ProductNumber
(restringida, a su vez, como una CLAVE EXTRANJERA que hace referencia aProduct.ProductNumber
) yStartDate
(señalando la Fecha particular en la que se compró un determinado Producto a un Precio específico ) .En caso de que los Productos se compren a Precios diferentes durante el mismo Día , en lugar de la
StartDate
columna, puede incluir uno etiquetado comoStartDateTime
que mantiene el Instant cuando se compra un Producto determinado a un Precio exacto . La CLAVE PRIMARIA tendría que declararse como(ProductNumber, StartDateTime)
.Como se demostró, la tabla mencionada es ordinaria, porque puede declarar las operaciones SELECT, INSERT, UPDATE y DELETE para manipular sus datos directamente, por lo tanto (a) permite evitar la instalación de componentes adicionales y (b) se puede utilizar en todos las principales plataformas SQL con algunos ajustes, si es necesario.
Muestras de manipulación de datos.
Para ejemplificar algunas operaciones de manipulación que parecen útiles, digamos que ha INSERTADO los siguientes datos en las tablas
Product
yPrice
, respectivamente:Dado que
Price.EndDate
es un punto de datos derivable, debe obtenerlo a través de, precisamente, una tabla derivada que se puede crear como una vista para producir la serie temporal "completa", como se ejemplifica a continuación:Luego, la siguiente operación que SELECCIONA directamente desde esa vista
suministra el siguiente conjunto de resultados:
Ahora, supongamos que está interesado en obtener todos los
Price
datos de losProduct
identificados principalmente paraProductNumber
1750 elDate
2 de junio de 2017 . Al ver que unaPrice
aserción (o fila) es actual o efectiva durante todo el intervalo que va desde (i)StartDate
a (ii) suEndDate
, entonces esta operación DMLproduce el conjunto de resultados que sigue
que aborda dicho requisito.
Como se muestra, la
PriceWithEndDate
vista juega un papel primordial en la obtención de la mayoría de los datos derivables, y se puede SELECCIONAR DESDE de una manera bastante ordinaria.Teniendo en cuenta que su plataforma de preferencia es PostgreSQL, este contenido del sitio de documentación oficial contiene información sobre vistas "materializadas" , que pueden ayudar a optimizar la velocidad de ejecución mediante mecanismos de nivel físico, si dicho aspecto se vuelve problemático. Otros sistemas de administración de bases de datos SQL (DBMS) ofrecen instrumentos físicos muy similares, aunque se pueden aplicar diferentes terminologías, por ejemplo, vistas "indexadas" en Microsoft SQL Server.
Puede ver los ejemplos de código DDL y DML discutidos en acción en este db <> fiddle y en este SQL Fiddle .
Recursos Relacionados
En estas preguntas y respuestas , discutimos un contexto comercial que incluye los cambios en los precios de los productos, pero tiene un alcance más amplio, por lo que puede resultarle interesante.
Estas publicaciones de desbordamiento de pila cubren puntos muy relevantes con respecto al tipo de columna que contiene un dato de moneda en PostgreSQL.
Respuestas a comentarios
El método que propongo anteriormente aborda un dominio comercial de las características descritas anteriormente , aplicando consecuentemente su sugerencia sobre declarar
EndDate
como una columna, que es diferente de un "campo", de la tabla base nombradaPrice
implicaría que la estructura lógica de la base de datos no debe reflejar el esquema conceptual correctamente, y un esquema conceptual debe definirse y reflejarse con precisión, incluida la diferenciación de (1) información base de (2) información derivable .Aparte de eso, tal curso de acción introduciría duplicación, ya que
EndDate
podría obtenerse en virtud de (a) una tabla derivable y también en virtud de (b) la tabla base nombradaPrice
, con laEndDate
columna por lo tanto duplicada . Si bien esa es una posibilidad, si un profesional decide seguir dicho enfoque, debe advertir decididamente a los usuarios de la base de datos acerca de los inconvenientes e ineficiencias que conlleva. Uno de esos inconvenientes e ineficiencias es, por ejemplo, la necesidad urgente de desarrollar un mecanismo que garantice, en todo momento , que cadaPrice.EndDate
valor sea igual al de laPrice.StartDate
columna de la fila inmediatamente sucesiva para elPrice.ProductNumber
valor en cuestión.En contraste, el trabajo para producir los datos derivados en cuestión, como lo expuse, honestamente, no es nada especial, y se requiere para (i) garantizar la correspondencia correcta entre los niveles lógicos y conceptuales de abstracción de la base de datos y (ii ) aseguran la integridad de los datos, ambos aspectos que, como se señaló anteriormente, son decididamente de gran importancia.
Si el aspecto de eficiencia del que está hablando está relacionado con la velocidad de ejecución de algunas operaciones de manipulación de datos, entonces debe gestionarse en el lugar apropiado, es decir, a nivel físico, mediante, por ejemplo, una estrategia de indexación ventajosa, basada en (1 ) las tendencias particulares de consulta y (2) los mecanismos físicos particulares proporcionados por el DBMS de uso. De lo contrario, sacrificar el mapeo conceptual-lógico apropiado y comprometer la integridad de los datos involucrados convierte fácilmente un sistema robusto (es decir, un activo organizacional valioso) en un recurso no confiable.
Series temporales discontinuas o disjuntas
Por otro lado, hay circunstancias en las que retener la
EndDate
fila de cada fila en una tabla de series de tiempo no solo es más conveniente y eficiente, sino que se exige , aunque eso depende por completo de los requisitos específicos del entorno empresarial, por supuesto. Un ejemplo de ese tipo de circunstancias se produce cuandoHe representado dicho escenario en el diagrama IDEF1X que se muestra en la Figura 2 .
En ese caso, sí, la
Price
tabla hipotética debe declararse de manera similar a esto:Y sí, ese diseño lógico DDL simplifica la administración a nivel físico, porque puede presentar una estrategia de indexación que abarque la
EndDate
columna (que, como se muestra, se declara en una tabla base) en configuraciones relativamente más fáciles .Luego, una operación SELECT como la siguiente
puede usarse para derivar todos los
Price
datos de losProduct
identificados principalmente paraProductNumber
1750 elDate
2 de junio de 2017 .fuente
Creo que querrás mirar las tablas temporales . Estos proporcionan funcionalidad para hacer exactamente lo que está buscando y están disponibles en Postgres con las extensiones adecuadas.
Este concepto también parece ser bastante independiente de DB, ya que se ofrece en una variedad de plataformas RDBMS .
fuente
Di una respuesta aquí que es relativamente simple y no requiere extensiones especiales de la base de datos (por lo tanto, funcionará con cualquier base de datos).
fuente