Lors du suivi de quelque chose comme l'historique des prix, dans ma base de données relationnelle, quelle est la manière recommandée de stocker des changements de tarification? Par exemple, je peux:
price_change_date
ou
effective_price_start_date
et effective_price_end_date
(AKA, lors de la saisie d'un nouveau prix, l'ancien enregistrement reçoit et mis à jour "Date de fin", et le nouvel enregistrement devient la date actuelle comme "Date de début" et null
(?) Pour "Date de fin"). C'est deux dates pour chaque enregistrement d'historique des prix.Je pense que la première approche - ne conserve que l'enregistrement de date unique qui signifie "C'est la date à laquelle le prix a été saisi" est suffisant. Et peut-être un peu plus simple à maintenir.
Cependant, j'ai vu des suggestions dans d'autres réponses qui recommandent de garder une durée effective du prix, c'est-à-dire la date de début des prix et la date de fin. Mais dans cette approche, il y a des complications telles que
null
puis interprétez-le comme "actuellement actif"?Existe-t-il des problèmes spécifiques que je ferai face si je choisis d'aller avec la première approche (une colonne de date) plutôt que la deuxième approche (deux colonnes de date par enregistrement)
objectif
L'objectif est des objectifs de l'audit et des questions des clients. I.E. HR demande à quoi nous avons-nous facturé la partie X en janvier 2015? Comment le découvrions-nous?
Ou le client dit pourquoi vous chargeez-vous 200 $ de plus pour cela par rapport à l'année dernière lorsque je vous ai commandé? Les ventes peuvent revenir en arrière et dire Oh oui, nous avons changé le prix en décembre pour cette raison ou cette raison.
Comment les changements sont des changements - disons que HR dirige que, en janvier, nous devrions facturer 100 $ pour la partie x, mais à partir de février chargé de 200 $.
conception de domaine axée sur l'approvisionnement de l'événement , affirmeriez que vous stockez les événements à l'aide d'une entrée immuable qui passe dans un journal des annexes. Vous stockez uniquement l'événement comme cela se produit, une date d'événement unique, (c'est-à-dire aucune date de fin).
Cependant, vous voulez également probablement connaître le prix actuel de tout, donc CQRS/ES dit que vous avez une autre table quelque part qui stocke simplement cela; La conception CQRS/ES appellerait ce tableau un cache, qui pourrait être jeté et reconstruit à volonté. (Alors, ils se concentrent sur le durcissement des bûches et non le cache.)
Lorsque vous stockez le prix actuel, vous n'avez pas besoin des informations de date de fin, car vous ne stockez que le prix actuel. Vous pouvez inclure une date de date, si vous le souhaitez, mais tout autre calcul concernant les prix anciens devra probablement revenir au magasin d'événements (ou stocker d'autres informations en cache).
(BTW, le magasin d'événements pourrait être la même base de données SQL ou quelque chose de différent.)
L'avantage de ceci est que les journaux immuables qu'aux annexes ne sont faciles dans une variété de technologies (SQL, NOSQL) et que le cache qui stocke la date actuelle n'est qu'une table très simple à utiliser.
Définitivement la deuxième approche est plus facile à travailler avec:
Lors de l'utilisation de la deuxième approche, la révolte à un prix précédent a d'abord être analysée d'une perspective commerciale:
Pour la date de fin de fin indéterminée, il y a deux écoles:
Je suis d'accord avec @christophe dans celui avec l'option 1 (une date unique par ligne) Trouver le prix pour une date donnée (en cours ou autrement) impliquerait la lecture de plusieurs enregistrements dans l'ordre (le moteur de base de données le fera, pas votre code). La requête serait comme ça:
select
price
from
price_history
where
product_id = myProductID
date <= myDate
order by date desc
limit 1;
Cette option a un avantage cependant: Vous n'avez pas à vous soucier des lacunes et des chevauchements (voir ci-dessous). Mais le gros inconvénient vient Lorsque vous souhaitez modifier les périodes de temps, car vous devrez jouer avec plusieurs enregistrements et passer les processus de manière séquentielle afin d'aller de l'avant.
La deuxième option est donc meilleure, car la requête serait aussi simple que:
select
price
from
price_history
where
product_id = myProductID and
from_date <= myDate and
( thru_date >= MyDate or thru_date is null);
Évidemment, je pense que le prix réel devrait avoir NULL dans la colonne thru_date Beause Whe, tout simplement ne pas avoir une date à travers.
Il y a des choses à prendre en compte cependant:
PRICE_HISTORY
doit être (PRODUCT_ID,FROM_DATE)
ou il devrait y avoir un index unique sur (PRODUCT_ID,FROM_DATE)
si vous préférez que le PK soit un substitut.THRU_DATE
. Déclencheur ou SP à nouveau.Bottom-Line:
Certaines personnes préfèrent l'option une (1 date par ligne) car cette façon n'a pas à respecter les lacunes et les chevauchements, mais la deuxième option est plus lisible par l'homme, imo.
En tout cas, ajoutez une table d'audit de prix pour refléter qui a changé quelle ligne une ligne quand. Si vous souhaitez enregistrer non seulement Old_Price et New_Price, mais aussi change dans de_date et thru_date, alors le PK sur la table PRICE_HISTORY
doit être un substitut. Et ne confondez pas PRICE_HISTORY
avec PRICE_AUDIT
. Une table a le prix des produits au fil du temps, la seconde détient des modifications apportées aux enregistrements sur le premier.
Voir Ces autres réponses liées aux changements de prix au fil du temps, y compris AUDIT_TABLE
et er diagrammes.
Je vais aller avec l'option 2 comme la plupart des gens. Une conséquence positive de Datedate et de Todate est que vous pouvez mettre en œuvre élégamment des réductions temporaires sans risquer des lacunes:
Table Product_Price
Product_ID Price FromDate ToDate
---------- ----- -------- --------
1 300 1/1/1900 Null
1 250 1/1/2016 8/1/2016
Ensuite, vous devez faire votre choix en obtenant le le plus bas Price valide à la date d'intérêt
Sauf si vous avez une circonstance très étrange où vous voulez un prix temporaire supérieur - auquel cas vous devez effectuer plusieurs inserts.
Un changement de prix permanent est mis en œuvre à l'aide d'une mise à jour de l'ancien prix avec une date de fin et d'une insertion du nouveau prix.