J'aurais besoin de suivre les changements de prix d'un produit afin de pouvoir interroger la base de données pour un prix de produit à une date donnée. Les informations sont utilisées dans un système qui calcule les audits historiques de sorte qu'il doit renvoyer le prix correct pour le produit correct en fonction de la date d'achat.
Je préférerais utiliser des postgres dans la construction de la base de données.
J'ai besoin de la conception de la base de données mais toutes les suggestions de meilleures pratiques sont également les bienvenues.
database-design
best-practices
Gunnar Norred
la source
la source
prices
créer une tableprices_history
avec des colonnes similaires. Hibernate Envers peut automatiser cela pour vousRéponses:
Si je comprends bien le scénario, vous devez définir une table qui conserve une série chronologique de prix ; par conséquent, je suis d'accord, cela a beaucoup à voir avec l' aspect temporel de la base de données avec laquelle vous travaillez.
Règles métier
Commençons par analyser la situation au niveau conceptuel. Donc, si , dans votre domaine d'activité,
alors cela signifie que
Le diagramme IDEF1X illustré à la figure 1 , bien que très simplifié, illustre un tel scénario:
Disposition logique d'exposition
Et la conception de niveau logique SQL-DDL suivante, basée sur ledit diagramme IDEF1X, illustre une approche réalisable que vous pouvez adapter à vos propres besoins exacts:
Le
Price
tableau a une CLÉ PRIMAIRE composite composée de deux colonnes, c'est-à-direProductNumber
(contrainte, à son tour, comme une CLÉ ÉTRANGÈRE qui fait référence àProduct.ProductNumber
) etStartDate
(indiquant la Date particulière à laquelle un certain Produit a été acheté à un Prix spécifique ) .Dans le cas où les produits sont achetés à des prix différents au cours du même jour , au lieu de la
StartDate
colonne, vous pouvez en inclure un étiqueté commeStartDateTime
qui conserve l' instantané lorsqu'un produit donné a été acheté à un prix exact . La CLÉ PRIMAIRE devrait alors être déclarée comme(ProductNumber, StartDateTime)
.Comme démontré, le tableau susmentionné est un tableau ordinaire, car vous pouvez déclarer des opérations SELECT, INSERT, UPDATE et DELETE pour manipuler directement ses données, ce qui (a) permet d'éviter l'installation de composants supplémentaires et (b) peut être utilisé dans tous les les principales plates-formes SQL avec quelques ajustements, si nécessaire.
Exemples de manipulation de données
Pour illustrer certaines opérations de manipulation qui semblent utiles, disons que vous avez INSÉRÉ respectivement les données suivantes dans les tableaux
Product
etPrice
:Étant donné que le
Price.EndDate
est un point de données dérivable, vous devez alors l'obtenir via, précisément, une table dérivée qui peut être créée sous forme de vue afin de produire la série temporelle «complète», comme illustré ci-dessous:Ensuite, l'opération suivante qui sélectionne directement à partir de cette vue
fournit le jeu de résultats suivant:
Supposons maintenant que vous souhaitez obtenir l'intégralité des
Price
données pour leProduct
principal identifié parProductNumber
1750 leDate
2 juin 2017 . Voyant qu'unePrice
assertion (ou ligne) est actuelle ou effective pendant tout l' intervalle qui va de (i) sonStartDate
à (ii) sonEndDate
, alors cette opération DMLdonne l'ensemble de résultats qui suit
qui répond à cette exigence.
Comme indiqué, la
PriceWithEndDate
vue joue un rôle primordial dans l'obtention de la plupart des données dérivables, et peut être sélectionnée à partir d'une manière assez ordinaire.Étant donné que votre plate-forme de préférence est PostgreSQL, ce contenu du site de documentation officiel contient des informations sur les vues «matérialisées» , qui peuvent aider à optimiser la vitesse d'exécution au moyen de mécanismes de niveau physique, si cet aspect devient problématique. D'autres systèmes de gestion de bases de données SQL (SGBD) offrent des instruments physiques très similaires, bien que des terminologies différentes puissent être appliquées, par exemple, des vues «indexées» dans Microsoft SQL Server.
Vous pouvez voir les exemples de code DDL et DML discutés en action dans ce violon db <> et dans ce violon SQL .
Ressources associées
Dans ce Q & A, nous discutons d'un contexte commercial qui inclut les changements de prix des produits mais a une portée plus étendue, vous pouvez donc le trouver intéressant.
Ces publications Stack Overflow couvrent des points très pertinents concernant le type de colonne contenant une donnée de devise dans PostgreSQL.
Réponses aux commentaires
La méthode que je propose ci-dessus concerne un domaine d'activité des caractéristiques décrites précédemment , en appliquant par conséquent votre suggestion de déclarer le en
EndDate
tant que colonne - qui est différente d'un «champ» - de la table de base nomméePrice
impliquerait que la structure logique de la base de données serait ne pas refléter correctement le schéma conceptuel, et un schéma conceptuel doit être défini et reflété avec précision, y compris la différenciation (1) des informations de base des (2) informations dérivables .En dehors de cela, une telle ligne de conduite introduirait une duplication, car elle
EndDate
pourrait alors être obtenue en vertu de (a) une table dérivable et également en vertu de (b) la table de base nomméePrice
, avec laEndDate
colonne donc dupliquée . Bien que cela soit une possibilité, si un praticien décide de suivre cette approche, il ou elle devrait décidément avertir les utilisateurs de la base de données des inconvénients et des inefficacités que cela implique. L'un de ces inconvénients et inefficacités est, par exemple, le besoin urgent de développer un mécanisme qui garantit, à tout moment , que chaquePrice.EndDate
valeur est égale à celle de laPrice.StartDate
colonne de la ligne immédiatement successive pour laPrice.ProductNumber
valeur en question.En revanche, le travail pour produire les données dérivées en question, comme je l'ai avancé, n'est honnêtement pas spécial du tout et est nécessaire pour (i) garantir la correspondance correcte entre les niveaux d'abstraction logiques et conceptuels de la base de données et (ii ) garantissent l'intégrité des données, deux aspects qui, comme indiqué précédemment, sont décidément d'une grande importance.
Si l'aspect d'efficacité dont vous parlez est lié à la vitesse d'exécution de certaines opérations de manipulation de données, alors il doit être géré à l'endroit approprié, c'est-à-dire au niveau physique, via, par exemple, une stratégie d'indexation avantageuse, basée sur (1 ) les tendances de requête particulières et (2) les mécanismes physiques particuliers fournis par le SGBD d'utilisation. Sinon, sacrifier le mappage conceptuel-logique approprié et compromettre l'intégrité des données impliquées transforme facilement un système robuste (c'est-à-dire un précieux actif organisationnel) en une ressource non fiable.
Séries chronologiques discontinues ou discontinues
D'un autre côté, il existe des circonstances dans lesquelles le maintien
EndDate
de chaque ligne dans un tableau de séries chronologiques est non seulement plus pratique et efficace, mais aussi exigé , bien que cela dépende entièrement des exigences spécifiques à l'environnement commercial, bien sûr. Un exemple de ce genre de circonstances survient lorsqueJ'ai représenté ledit scénario dans le diagramme IDEF1X illustré à la figure 2 .
Dans ce cas, oui, le
Price
tableau hypothétique doit être déclaré d'une manière similaire à ceci:Et, oui, cette conception DDL logique simplifie l'administration au niveau physique, car vous pouvez mettre en place une stratégie d'indexation qui englobe la
EndDate
colonne (qui, comme illustré, est déclarée dans une table de base) dans des configurations relativement plus faciles .Ensuite, une opération SELECT comme celle ci-dessous
peut être utilisé pour dériver l'ensemble des
Price
données pour lesProduct
principales identifiées parProductNumber
1750 leDate
2 juin 2017 .la source
Je crois que vous allez vouloir regarder les tables temporelles . Ceux-ci fournissent des fonctionnalités pour faire exactement ce que vous cherchez et sont disponibles dans Postgres avec les extensions appropriées.
Ce concept semble également être assez indépendant de la base de données, car il est proposé sur une variété de plates-formes RDBMS .
la source
J'ai donné ici une réponse qui est relativement simple et ne nécessite aucune extension spéciale à la base de données (fonctionnera donc avec n'importe quelle base de données).
la source