2011-08-23 11 views
8

Fornirò un contesto in modo che abbia senso. Sto catturando le valutazioni dei clienti per i prodotti in una tabella (valutazione) e voglio essere in grado di restituire una media mobile cumulativa dei rating in base al tempo.Come calcolare la media mobile cumulativa in Python/SQLAlchemy/Flask

Un esempio di base segue prendere un voto al giorno:

02 FEB - Rating: 5 - Cum Avg: 5 
03 FEB - Rating: 4 - Cum Avg: (5+4)/2 = 4.5 
04 FEB - Rating: 1 - Cum Avg: (5+4+1)/3 = 3.3 
05 FEB - Rating: 5 - Cum Avg: (5+4+1+5)/4 = 3.75 
Etc... 

Sto cercando di pensare a un approccio che non scalerà orribilmente.

La mia idea attuale è quella di avere una funzione che è scattato quando una riga viene inserita nella tabella di valutazione che funziona il Cum Avg base alla riga precedente per quel prodotto

Così i campi sarebbe qualcosa di simile:

TABLE: Rating 
| RatingId | DateTime | ProdId | RatingVal | RatingCnt | CumAvg | 

Ma questo sembra un modo abbastanza dubbia per archiviare i dati.

Quale sarebbe il (o qualsiasi) modo per realizzare questo? Se dovessi usare il 'trigger' di sorta, come si fa a farlo in SQLAlchemy?

Qualsiasi consiglio è apprezzato!

+1

È possibile eseguire questa operazione in SQL: consultare: http://stackoverflow.com/questions/4107479/subqueries-aggregates-and-aggravation/4107784#4107784 ... Non sono sicuro di come ottenere SQLAlchemy per generare una query simile (e il tuo database potrebbe non supportare la sintassi necessaria.) –

+0

@Sean Vieria: Grazie per il link: so che è possibile in SQL puro, ma ancora una volta questo significa che il numero di voti aumenta, le prestazioni peggiora quando i calcoli vengono fatti su ogni riga. Potrei provare a implementare la mia idea originale di archiviarlo man mano che ogni riga viene inserita come so che verrà scalata. Non ero sicuro se ci fosse qualcosa di fondamentale che stavo trascurando. Grazie per l'aiuto! – mwan

risposta

5

Non so su SQLAlchemy, ma potrei usare un approccio In questo modo:

  • Memorizza la media cumulativa e il conteggio del rating separatamente dai singoli rating.
  • Ogni volta che si ottiene un nuovo rating, aggiornare la media e punteggio conteggio cumulativo:
    • NEW_COUNT = old_count + 1
    • new_average = ((old_average * old_count) + new_rating)/NEW_COUNT
  • Facoltativamente, memorizza una riga per ogni nuova classificazione.

L'aggiornamento della media e del conteggio delle valutazioni potrebbe essere eseguito con una singola istruzione SQL.

+0

Grazie, ho implementato la maggior parte di esso ieri e questo è l'approccio che ho finito per prendere comunque, devo solo finire di implementarlo e poi posterò il codice che ho usato.Scala in modo responsabile e prevedibile, che è quello che cercavo. – mwan

+0

E se l'utente può modificare la valutazione? Questo approccio funzionerebbe? – user2990084

+1

È molto più facile memorizzare la * somma * e il conteggio, piuttosto che la * media * e il conteggio. –

-5

Penso che si dovrebbe conservare il Master in una lista 2 elemento, sarebbe molto più semplice:

#first rating 5 is rating number 0 
a = [5,0] 

#next: 
for i in rating: 
a = [(a[0]*a[1]+lastRating)/(a[1]+1),a[1]+1] 

Bye

+0

Stai suggerendo di archiviare la lista Python-side (cioè devo ricalcolare l'intero elenco per ogni query che viene eseguita)? Non sono sicuro di seguirlo. Non si ridurrebbe questa scala con l'aumento del numero di ascolti? – mwan