2009-12-10 12 views
7

Fondamentalmente voglio aggregare alcuni valori in una tabella in base a un intervallo di tempo.Dati aggregati in un intervallo temporale in MySQL

Quello che faccio è scattare istantanee di un sistema ogni 15 minuti e voglio essere in grado di disegnare un grafico per un lungo periodo. Dal momento che i grafici diventano davvero confusi se vengono mostrati troppi punti (oltre ad essere molto lenti nel rendering) voglio ridurre il numero di punti aggregando più punti in un singolo punto mediando su di essi.

Per questo dovrei essere in grado di raggruppare per bucket che possono essere definiti da me (giornaliero, settimanale, mensile, annuale, ...) ma finora tutti i miei esperimenti non hanno avuto fortuna.

C'è qualche trucco che posso applicare per farlo?

risposta

10

Avevo una domanda simile: collating-stats-into-time-chunks e aveva risposto molto bene. In sostanza, la risposta è stata:

Forse è possibile utilizzare la funzione DATE_FORMAT() e il raggruppamento. Ecco un esempio, si spera che tu possa adattarti alle tue esigenze precise.

SELECT 
    DATE_FORMAT(time, "%H:%i"), 
    SUM(bytesIn), 
    SUM(bytesOut) 
FROM 
    stats 
WHERE 
    time BETWEEN <start> AND <end> 
GROUP BY 
    DATE_FORMAT(time, "%H:%i") 

Se la finestra di tempo si estende su più di un giorno e si utilizza il formato di esempio, i dati provenienti da diversi giorni saranno aggregate in secchi 'ora-di-giorno. Se i dati grezzi non rientrano esattamente nell'ora, puoi arrotondare utilizzando "% H: 00".

Grazie a martin Clayton per la risposta che mi ha fornito.

+0

Questo scala? Il mio problema è che questo produrrà diversi milioni di voci dopo un anno. – cdecker

+1

Non riesco a capire perché non lo farebbe. Ovviamente fare qualsiasi tipo di conversioni temporali è lento, ma la maggior parte del tempo verrà speso nell'aggregazione dei dati stessi, il che è inevitabile nel tuo caso. – cmroanirgo

2

E 'facile per troncare volte per gli ultimi 15 minuti (per esempio), facendo qualcosa di simile:

SELECT dateadd(minute, datediff(minute, '20000101', yourDateTimeField)/15 * 15, '20000101') AS the15minuteBlock, COUNT(*) as Cnt 
FROM yourTable 
GROUP BY dateadd(minute, datediff(minute, '20000101', yourDateTimeField)/15 * 15, '20000101'); 

Utilizzare simili metodi di troncamento a gruppo per ora, settimana, qualunque sia.

Si può sempre avvolgetelo in una dichiarazione CASE per gestire più metodi, usando:

GROUP BY CASE @option WHEN 'week' THEN dateadd(week, .....