2009-06-02 12 views
3

Problem:Computing Mittelwert über Abschnitte von Datum/Uhrzeit

Ich habe eine Datenbank mit Sensormess mit einem Zeitstempel für die Zeit wurde der Sensor gelesen. Grundsätzlich sieht es so aus:

Sensor | Timestamp | Value 

Jetzt möchte ich ein Diagramm aus diesen Daten machen und ich möchte mehrere verschiedene Grafiken machen. Sagen wir, ich möchte einen für den letzten Tag, einen für die letzte Woche und einen für den letzten Monat. Die Auflösung jedes Diagramms ist unterschiedlich, so dass die Auflösung für das Tagesdiagramm 1 Minute beträgt. Für die Wochengrafik wäre es eine Stunde und für die Monatsgrafik wäre es ein Tag oder ein Viertel eines Tages.

So würde ich eine Ausgabe wie die der Durchschnitt der jeweiligen Auflösung (zB Tag = Mittelwert über die Minute, Woche = Mittelwert über die Stunde und so weiter.)

Ex:

Sensor | Start | End | Average 

Wie mache ich das einfach und schnell in mySQL? Ich vermute, dass es sich um das Erstellen einer temporären Tabelle oder um das Sortieren der Sensordaten handelt, um die Durchschnittswerte des Sensors zu ermitteln. Aber mein Wissen über mySQL ist bestenfalls begrenzt.

Gibt es einen wirklich cleveren Weg, dies zu tun?

Antwort

7
SELECT DAY(Timestamp), HOUR(Timestamp), MINUTE(Timestamp), AVG(value) 
FROM mytable 
GROUP BY 
     DAY(Timestamp), HOUR(Timestamp), MINUTE(Timestamp) WITH ROLLUP 

WITH ROLLUP Klausel hier erzeugt zusätzliche Zeilen mit Mitteln für jede HOUR und DAY, wie folgt aus:

SELECT DAY(ts), HOUR(ts), MINUTE(ts), COUNT(*) 
FROM (
     SELECT CAST('2009-06-02 20:00:00' AS DATETIME) AS ts 
     UNION ALL 
     SELECT CAST('2009-06-02 20:30:00' AS DATETIME) AS ts 
     UNION ALL 
     SELECT CAST('2009-06-02 21:30:00' AS DATETIME) AS ts 
     UNION ALL 
     SELECT CAST('2009-06-03 21:30:00' AS DATETIME) AS ts 
     ) q 
GROUP BY 
     DAY(ts), HOUR(ts), MINUTE(ts) WITH ROLLUP 
 
2, 20, 0, 1 
2, 20, 30, 1 
2, 20, NULL, 2 
2, 21, 30, 1 
2, 21, NULL, 1 
2, NULL, NULL, 3 
3, 21, 30, 1 
3, 21, NULL, 1 
3, NULL, NULL, 1 
NULL, NULL, NULL, 4 

2, 20, NULL, 2 bedeutet hier, dass COUNT(*)2 für DAY = 2, HOUR = 20 und alle Minuten ist.

+0

Dies erzeugt etwas, das nah an den Ergebnissen ist, die ich erwarte. Was macht "WITH ROLLUP", weil es scheinbar die gleichen Ergebnisse liefert, wenn ich es entferne? –

+1

Von MySQL-Referenzhandbuch: „a WITH ROLLUP Modifikator auf die GROUP BY-Klausel Hinzufügen bewirkt, dass die Abfrage eine weitere Zeile zu erzeugen, die die Gesamtsumme über alle Werte zeigt“ – nightcoder

+0

Ich vermute, ich nur, was Datumsfunktion zu tun, um die Gruppierung verwenden könnte so dass es einfacher ist, die verschiedenen Graphen zu machen, das ist genau das was ich gesucht habe. Vielen Dank. –

2

Nicht ganz Ergebnistabelle Sie wollten, aber hier ist ein Starter dafür eine 1 Minute Auflösung:

SELECT sensor,minute(timestamp),avg(value) 
FROM table 
WHERE <time period specifier limits to a single hour> 
GROUP BY sensor, minute(timestamp) 
2

Ich habe Code sehr ähnlich wie diese verwendet wird (nicht getestet, aber es ist von der Arbeit Code nehmen)

die Variablen gesetzt:

$seconds = 3600; 
$start = mktime(...); // say 2 hrs ago 
$end = .... // 1 hour after $start 

dann

SELECT MAX(`when`) AS top_When, MIN(`when`) AS low_When, 
    ROUND(AVG(sensor)) AS Avg_S, 
    (MAX(`when`) - MIN(`when`)) AS dur, /* the duration in seconds of the actual period */ 
    ((floor(UNIX_TIMESTAMP(`when`)/$seconds)) * $seconds) as Epoch 
    FROM `sensor_stats` 
    WHERE `when` >= '$start' AND `when` <= '$end' and duration=30 
    GROUP BY Epoch/*((floor(UNIX_TIMESTAMP(`when`)/$seconds)) * $seconds)*/ 

Die die Abfrage ausführen Das hat den Vorteil, dass Sie beliebig viele Zeitperioden haben können - und nicht einmal "runde Zahlen" haben müssen, wie eine ganze Stunde (sogar eine Minute, 0-59).

+0

Ich kann diese Abfrage nicht funktionieren: "Unbekannte Spalte 'Dauer' in 'Where-Klausel'". Funktioniert nicht, wenn ich die Dauer durch entweder ersetze. –

+0

In meiner ursprünglichen Datenbank speichere ich, wie lange ein Zeitraum für diese Daten ist (vielleicht 30 Sekunden, vielleicht eine Stunde, vielleicht ein Tag). Sie können diesen Teil der Abfrage wahrscheinlich löschen ('und duration = 30'), da Ihre eigene Tabelle ein Punkt-in-Zeit-Datensatz ist. –