Pregunta

Problema:

Tengo una base de datos de lecturas de sensores con una marca de tiempo del momento en que se leyó el sensor.Básicamente se ve así:

Sensor | Timestamp | Value

Ahora quiero hacer un gráfico a partir de estos datos y quiero hacer varios gráficos diferentes.Digamos que quiero uno para el último día, uno para la última semana y otro para el último mes.La resolución de cada gráfico será diferente, por lo que para el gráfico diurno la resolución sería de 1 minuto.Para el gráfico semanal sería una hora y para el gráfico mensual sería un día o un cuarto de día.

Entonces me gustaría un resultado que sea el promedio de cada resolución (por ejemplo.Día = Promedio por minuto, Semana = Promedio por hora, etc.)

Ex:

Sensor | Start | End | Average

¿Cómo hago esto fácil y rápidamente en mySQL?Sospecho que implica crear una tabla o clasificación temporal y unir los datos del sensor para obtener los valores promedio del sensor.Pero mi conocimiento de MySQL es, en el mejor de los casos, limitado.

¿Existe una forma realmente inteligente de hacer esto?

¿Fue útil?

Solución

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

cláusula WITH ROLLUP aquí produce filas adicionales con promedios de cada HOUR y DAY, como esto:

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 aquí significa que es COUNT(*) 2 para DAY = 2, HOUR = 20 y todos los minutos.

Otros consejos

No es exactamente la tabla de resultados que quería, pero aquí hay un motor de arranque para hacer una resolución de 1 minuto:

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

He usado un código muy similar a este (no probado, pero está tomado del código de trabajo)

establecer las variables:

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

luego ejecuta la consulta

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

La ventaja de esto es que puede tener los períodos de tiempo que desee, y ni siquiera es necesario tenerlos en "números redondos", como una hora de reloj completa (incluso un minuto de reloj, 0-59).

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top