Wie speichere ich Preise mit Gültigkeitsdatum?

21

Ich habe eine Liste von Produkten. Jeder von ihnen wird von N Anbietern angeboten.

Jeder Anbieter bietet uns einen Preis für einen bestimmten Termin an. Dieser Preis gilt so lange, bis dieser Anbieter einen neuen Preis festlegt. In diesem Fall gibt der Anbieter den neuen Preis mit einem neuen Datum an.

Der MySQL-Tabellenheader sieht derzeit folgendermaßen aus:

provider_id, product_id, price, date_price_effective

Jeden zweiten Tag erstellen wir eine Liste der Produkte / Preise, die für den aktuellen Tag gültig sind. Für jedes Produkt enthält die Liste eine sortierte Liste der Anbieter, die dieses bestimmte Produkt haben. Auf diese Weise können wir bestimmte Produkte bei demjenigen bestellen, der gerade den besten Preis anbietet.

Um die effektiven Preise zu erhalten, habe ich eine SQL-Anweisung, die alle Zeilen zurückgibt, die haben date_price_effective >= NOW(). Diese Ergebnismenge wird mit einem Ruby-Skript verarbeitet, das die Sortierung und Filterung vornimmt, die erforderlich sind, um eine Datei zu erhalten, die wie folgt aussieht:

product_id_1,provider_1,provider_3,provider8,provider_10...
product_id_2,provider_3,provider_2,provider1,provider_10...

Für unsere Zwecke funktioniert dies einwandfrei, aber ich habe immer noch das Gefühl, dass eine SQL-Tabelle wahrscheinlich nicht der beste Weg ist, um diese Art von Informationen zu speichern. Ich habe das Gefühl, dass diese Art von Problem auf andere kreativere Weise gelöst wurde.

Gibt es eine bessere Möglichkeit zum Speichern dieser Informationen als in SQL? Oder gibt es bei Verwendung von SQL einen besseren Ansatz als den, den ich verwende?

edmz
quelle
lal00: ​​Wie ich in einem meiner Kommentare erwähnt habe, kümmere ich mich regelmäßig um effektive Datierung. Bitte sehen Sie meine Antwort für eine einfache effektive Datumsbehandlungsmethode. Es ist nicht erforderlich, dass man den Zeitraum kennt, in dem ein Preis wirksam ist, wenn eine neue Preiszeile erstellt wird, und es ist auch nicht erforderlich, dass man zurückgeht und die vorherige aktuellste Zeile ändert, wenn eine neue Zeile erstellt wird.
Bit Twiddler

Antworten:

17

Ich empfehle, das Buch "Zeitorientierte Entwicklung" zu lesen, wenn Sie Fragen haben, die von der Zeit abhängen (z. B. "Was war der Preis für X am Datum D?" Oder "Welche Kuh befand sich am Datum E?") Datenbankanwendungen in SQL. " Während dieses Buch vergriffen ist, hat der Autor das PDF des Buches sowie die dazugehörige CD freundlicherweise auf seiner Website zur Verfügung gestellt.

http://www.cs.arizona.edu/~rts/publications.html (suchen Sie den ersten Artikel unter "books").

Eine kurze Online-Einführung finden Sie unter:

Tangurena
quelle
1
Nun, das ist nicht das, was ich gedacht habe, als ich gefragt habe, es ist besser! :)
Edmz
3

Ich würde das Datum des Inkrafttretens auf jeden Fall in der Datenbank speichern. Schließlich ist es wahrscheinlich, dass die Leute in der Lage sein werden, Abfragen durchzuführen, um zu sehen, wie sich der Preis im Laufe der Zeit geändert hat, oder um Ungereimtheiten in Aufträgen mit der historischen Produktpreistabelle abzugleichen. Abhängig von der Art der von Ihnen ausgeführten Abfragen und der Häufigkeit von Preisänderungen kann es sinnvoll sein, separate Tabellen für den aktuellen Preis und die historischen Preise zu haben.

In den meisten Systemen, in denen Preise gespeichert werden, ist zusätzlich zum Datum des Inkrafttretens eine Spalte mit dem Verfallsdatum erforderlich, um leichter feststellen zu können, welcher Preis derzeit gültig ist, da Sie nicht in der vorherigen oder nächsten Zeile nachsehen müssen herauszufinden, welcher Preis zu einem bestimmten Zeitpunkt gültig war. Ich NOW() >= date_price_effectiveweiß nicht genau, was Ihr Zustand tut - vermutlich liefert er den aktuellen Kurs zusammen mit allen früheren historischen Kursen, die mir merkwürdig vorkommen. Ich würde denken, dass der "effektive Preis" der aktuelle Preis ist, der durch so etwas wie definiert wirdNOW() BETWEEN date_price_effective AND date_price_expired

Ich bin mir auch nicht sicher, wie Ihre Datei aussehen soll. Mir ist nicht klar, was - provider_1die provider_id = 1 Preis darstellt? - oder wie Sie die Anbieterdaten bestellen. Warum wird provider_1zuerst für product_id_1und drittens für angezeigt product_id_2.

Justin Cave
quelle
Justin, das Verfallsdatum macht Sinn. Sie hatten recht, ich hatte die SQL umgekehrt. Die Ausgabedatei ist für meine Frage nicht sehr relevant. Ich habe sie nur hinzugefügt, um zu veranschaulichen, dass ich die Produkte nach Preis sortieren musste.
Edmz
Man muss kein Ablaufdatum in jede Zeile einfügen, da dies nur zusätzlichen Aufwand verursacht, da man normalerweise nicht den Zeitraum kennt, in dem ein Preis gültig ist, wenn die Zeile erstellt wird. Wenn wir N Zeilen für jedes Producer_id / Product_id-Paar in einer Tabelle haben, von denen jede an einem bestimmten Datum wirksam ist, ist die Zeile mit dem größten date_price_effective-Wert, der kleiner oder gleich einem bestimmten Datum ist, der Preis, der am wirksam ist dieses Datum. Wenn Sie sich meinen Beitrag ansehen, sehen Sie SQL-Code, der diese Art von Abfrage ausführt. Ich muss mich regelmäßig mit Stichtagen auseinandersetzen.
Bit-Twiddler
@ Bit-Twiddler - Natürlich ist es nicht erforderlich, ein Ablaufdatum zu haben. Ein Ablaufdatum macht das Abfragen der Tabelle jedoch im Allgemeinen viel einfacher und effizienter. Da Abfragen zum effektiven Datum in der Regel weitaus häufiger sind als Preisänderungen, ist dies in der Regel ein Kompromiss, den ich gerne eingehen möchte.
Justin Cave
3

Wenn ich Ihre Problemstellung richtig verstehe, benötigen Sie eine Möglichkeit, mit Generationsdaten umzugehen (dh, die Tabelle enthält mehrere Zeilen für jedes Paar provider_id / product_id, von denen jede datumsabhängig ist). In diesem Fall suchen Sie nach dem neuesten Preis für ein Produkt mit einem Wert von date_price_effective, der kleiner oder gleich dem heutigen Wert ist. Diese Art von Situation ist mit einer SQL-Unterauswahl einfach zu handhaben.

 SELECT 
   provider_id, product_id, price, date_price_effective 
 FROM 
   price_table a 
 WHERE 
   date_price_effective = 
     (
       SELECT 
         MAX(date_price_effective) 
       FROM 
         price_table b 
       WHERE 
         b.provider_id = a.provider_id AND 
         b.product_id = a.product_id AND
         b.date_price_effective <= NOW() 
     );

Ein Preis ist gültig, solange er den größten Wert für date_price_effective hat, der kleiner oder gleich dem Datum ist, an dem die Abfrage ausgeführt wird. Ein date_price_effective-Wert, der größer als heute ist, ist ein zukünftiges Gültigkeitsdatum. Der oben aufgeführte Code gibt die Zeilendaten für jedes Anbieter-ID / Produkt-ID-Paar zurück, das den Wert date_price_effective aufweist, der dem Datum der Ausführung der Abfrage am nächsten, jedoch nicht später liegt. Die Lösung stuft die Preise automatisch in effektive Datumsbereiche ein. Der Primärschlüssel für diese Tabelle wäre das Triple {provider_id, product_id, date_price_effective};

Bit-Twiddler
quelle