2009-06-02 10 views
3

Problème:calcul des valeurs moyennes sur des sections de date/heure

J'ai une base de données de lectures de capteurs avec un horodatage pour le moment a été lu le capteur. Fondamentalement, il ressemble à ceci:

Sensor | Timestamp | Value 

Maintenant, je veux faire un graphique de ces données et je veux faire plusieurs graphiques différents. Dire que je veux un pour le dernier jour, un pour la dernière semaine et un pour le dernier mois. La résolution de chaque graphique sera différente, donc pour le graphique du jour, la résolution sera d'une minute. Pour le graphique de la semaine, ce serait une heure et pour le graphique du mois, ce serait un jour ou un quart de journée.

Je voudrais donc une sortie qui est la moyenne de chaque résolution (par exemple jour = moyenne sur la minute, Semaine = moyenne sur l'heure et ainsi de suite.)

Ex:

Sensor | Start | End | Average 

Comment faire cela facilement et rapidement dans mySQL? Je soupçonne qu'il permet de créer une table temporaire ou trie et joint les données du capteur avec cela pour obtenir les valeurs moyennes du capteur? Mais ma connaissance de mySQL est limitée au mieux.

Y a-t-il une manière vraiment intelligente de faire ceci?

Répondre

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

WITH ROLLUP ici produit des lignes supplémentaires avec des moyennes pour chaque HOUR et DAY, comme ceci:

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 signifie ici que COUNT(*) est 2 pour DAY = 2, HOUR = 20 et toutes les minutes.

+0

Cela produit quelque chose qui est proche des résultats que j'attends. Que fait le "WITH ROLLUP" parce qu'il semble qu'il produit les mêmes résultats si je l'enlève? –

+1

From MySQL Reference Manual: "L'ajout d'un modificateur WITH ROLLUP à la clause GROUP BY entraîne la création d'une autre ligne qui affiche le total général sur toutes les valeurs" – nightcoder

+0

Je suppose que je pourrais utiliser n'importe quelle fonction de date pour effectuer le regroupement pour que ce soit plus facile de faire les différents graphiques, c'est exactement ce que je cherchais. Merci. –

2

Pas tout à fait le tableau de résultat que vous vouliez, mais voici une entrée pour faire une résolution de 1 minute:

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

J'ai code utilisé très similaire à celui (non testé, mais il prend du code de travail)

définir les variables:

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

puis exécutez la requête

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)*/ 

Le L'avantage de ceci est que vous pouvez avoir toutes les périodes de temps que vous voulez - et même pas nécessaire de les avoir sur des «nombres ronds», comme une horloge complète (même une horloge-minute, 0-59).

+0

Je n'arrive pas à faire fonctionner cette requête: "Unknown column 'duration" dans' where clause '". Ne fonctionne pas si je remplace la durée par dur non plus. –

+0

Dans ma base de données d'origine, je stocke la période pendant laquelle les données sont utilisées (peut-être 30 secondes, peut-être une heure, peut-être un jour). Vous pouvez probablement supprimer cette partie de la requête ('and duration = 30') car votre propre table est un enregistrement à un point dans le temps. –