Come conservare i prezzi con date effettive?


21

Ho un elenco di prodotti. Ognuno di essi è offerto da N provider.

Ogni fornitore ci indica un prezzo per una data specifica. Tale prezzo è valido fino a quando il fornitore non decide di stabilire un nuovo prezzo. In tal caso, il fornitore fornirà il nuovo prezzo con una nuova data.

L'intestazione della tabella MySQL attualmente appare come:

provider_id, product_id, price, date_price_effective

A giorni alterni, compiliamo un elenco di prodotti / prezzi che sono in vigore per il giorno corrente. Per ciascun prodotto, l'elenco contiene un elenco ordinato dei fornitori che dispongono di quel particolare prodotto. In questo modo, possiamo ordinare determinati prodotti da chiunque capiti di offrire il miglior prezzo.

Per ottenere i prezzi effettivi, ho un'istruzione SQL che restituisce tutte le righe che hanno date_price_effective >= NOW(). Tale set di risultati viene elaborato con uno script ruby ​​che esegue l'ordinamento e il filtro necessari per ottenere un file simile al seguente:

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

Questo funziona bene per i nostri scopi, ma ho ancora il prurito che una tabella SQL non sia probabilmente il modo migliore per archiviare questo tipo di informazioni. Ho la sensazione che questo tipo di problema sia stato precedentemente risolto in altri modi più creativi.

Esiste un modo migliore per archiviare queste informazioni se non in SQL? o, se si utilizza SQL, esiste un approccio migliore di quello che sto usando?


lal00: ​​Come ho già detto in uno dei miei commenti, gestisco la datazione efficace su base regolare. Si prega di consultare la mia risposta per un metodo di gestione della data semplice ed efficace. Non richiede di conoscere il periodo in cui un prezzo è efficace quando viene creata una nuova riga di prezzo, né richiede di tornare indietro per modificare la riga più recente precedente quando viene creata una nuova riga.
twiddler

Risposte:


17

Per gli articoli che variano in base al tempo (come la possibilità di rispondere a cose come "qual era il prezzo di X alla data D" o "quale mucca era nel feedlot Q alla data E") ti consiglio di leggere il libro "Sviluppo orientato al tempo Applicazioni di database in SQL. " Mentre questo libro è esaurito, l'autore ha gentilmente reso disponibile il PDF del libro e il CD associato sul suo sito web.

http://www.cs.arizona.edu/~rts/publications.html (cerca il primo elemento in "libri").

Per una breve introduzione online, vedere:


1
Bene, questo non è quello che avevo in mente quando ho chiesto, è meglio! :)
edmz,

3

Conserverei sicuramente la data di entrata in vigore nel database. Dopotutto, è probabile che le persone vorranno essere in grado di eseguire query per vedere come il prezzo è cambiato nel tempo o per verificare le stranezze degli ordini rispetto alla tabella dei prezzi dei prodotti storici. A seconda del tipo di query in esecuzione e della frequenza delle variazioni dei prezzi, può essere utile disporre di tabelle separate per il prezzo corrente e i prezzi storici.

Nella maggior parte dei sistemi che memorizzano i prezzi, si desidera una colonna della data di scadenza oltre alla data di validità per rendere più semplice determinare quale prezzo è attualmente in vigore poiché consente di risparmiare il problema di dover guardare la riga precedente o successiva per capire di quale prezzo era in vigore in un determinato momento. Non sono chiaro su cosa NOW() >= date_price_effectivestia facendo la tua condizione, presumibilmente, ciò restituisce il prezzo corrente insieme a tutti i prezzi storici precedenti che mi sembrano strani. Penserei che il "prezzo effettivo" sarebbe il prezzo attuale che sarebbe definito da qualcosa di simileNOW() BETWEEN date_price_effective AND date_price_expired

Inoltre, non sono sicuro di come dovrebbe essere il tuo file. Non mi è chiaro cosa provider_1rappresenti - il provider_id = 1 prezzo? - o come stai ordinando i dati del provider - perché provider_1appare prima product_id_1e terza per product_id_2.


Giustino, la data di scadenza ha senso. Avevi ragione, avevo l'SQL al contrario. Il file di output non è molto rilevante per la mia domanda, ho appena aggiunto un modo per esemplificare che avevo bisogno di ordinare i prodotti per prezzo.
edmz,

Non è necessario includere una data di scadenza in ogni riga, in quanto ciò aggiunge solo un sovraccarico aggiuntivo, poiché di solito non viene assegnato il periodo in cui un prezzo è effettivo al momento della creazione della riga. Se in una tabella sono presenti N righe per ciascuna coppia producer_id / product_id, ognuna delle quali è effettiva in una determinata data, la riga con il valore data_prezzo_più grande che è inferiore o uguale a una data specifica è il prezzo in vigore su quella data. Se guardi i miei post, vedrai il codice SQL che esegue questo tipo di query. Devo occuparmi di date effettive su base regolare.
twiddler

@ bit-twiddler - Certamente, non è necessario avere una data di scadenza. Tuttavia, avere una data di scadenza generalmente rende l'interrogazione della tabella molto più semplice ed efficiente. Poiché le query sulla data effettiva sono generalmente molto più comuni delle variazioni di prezzo, è generalmente un compromesso che sono felice di fare.
Grotta di Giustino,

3

Se capisco correttamente la tua affermazione del problema, hai bisogno di un modo per gestire i dati generazionali (ad esempio, la tabella contiene più righe per ogni coppia provider_id / product_id ciascuna delle quali è sensibile alla data). In tal caso, stai cercando il prezzo più recente per un prodotto con un valore data_prezzo_effettivo inferiore o uguale a oggi. Questo tipo di situazione è facile da gestire usando una sottoselezione SQL.

 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() 
     );

Un prezzo è valido purché abbia il valore di date_price_effective maggiore che sia inferiore o uguale alla data di esecuzione della query. Un valore di date_price_effective che è maggiore di oggi è una data di efficacia futura. Il codice sopra elencato restituisce i dati di riga per ogni coppia provider_id / product_id che ha il valore data_prezzo_effettivo che è il più vicino, ma non oltre la data di esecuzione della query. La soluzione raggruppa automaticamente i prezzi in intervalli di date effettivi. La chiave primaria per questa tabella sarebbe la tripla {provider_id, product_id, date_price_effective};

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.