2012-05-24 93 views
11

Tengo un número de publicaciones guardadas en una tabla InnoDB en MySQL. La tabla tiene las columnas "id", "date", "user", "content". Yo quería hacer algunos gráficos estadísticos, así que terminé usando la siguiente consulta para obtener la cantidad de mensajes por hora de ayer:Promedio de mensajes por hora en MySQL?

SELECT HOUR(FROM_UNIXTIME(`date`)) AS `hour`, COUNT(date) from fb_posts 
WHERE DATE(FROM_UNIXTIME(`date`)) = CURDATE() - INTERVAL 1 DAY GROUP BY hour 

Esto da salida a los datos siguientes:

table data

I puedo editar esta consulta para obtener el día que quiera. Pero lo que quiero ahora es el PROMEDIO de cada hora de cada día, de modo que si el día 1 a las 00 horas tengo 20 publicaciones y el día 2 a las 00 horas tengo 40, quiero que la salida sea "30". También me gustaría poder elegir períodos de fechas si es posible.

¡Gracias de antemano!

Respuesta

6

Puede usar una subconsulta para agrupar los datos por día/hora, y luego tomar el promedio por hora en la subconsulta.

He aquí un ejemplo para darle el recuento promedio por hora durante los últimos 7 días:

select the_hour,avg(the_count) 
from 
(
    select date(from_unixtime(`date`)) as the_day, 
    hour(from_unixtime(`date`)) as the_hour, 
    count(*) as the_count 
    from fb_posts 
    where `date` >= unix_timestamp(current_date() - interval 7 day) 
    and created_on < unix_timestamp(current_date()) 
    group by the_day,the_hour 
) s 
group by the_hour 
+0

¿por qué agrega una "s" después de la (...) subconsulta? –

+1

Ese es un alias para la subconsulta, que se requiere en MySQL para evitar este error: 'ERROR 1248 (42000): cada tabla derivada debe tener su propio alias'. Podría ser más detallado con él si lo desea y usar algo como 'como sub_query'. –

+0

Oh, ya veo. Aunque la solución de Linoff fue muy similar, esta es la que me ayudó a entender SQL mucho más. ¡Gracias! –

0

agregar la información de fecha y hora, y luego tomar el promedio por hora:

select hour, avg(numposts) 
from (SELECT date(`date`) as day, HOUR(FROM_UNIXTIME(`date`)) AS `hour`, 
      count(*) as numposts 
     from fb_posts 
     WHERE DATE(FROM_UNIXTIME(`date`)) between <date1> and <date2> 
     GROUP BY date(`date`), hour 
    ) d 
group by hour 
order by 1 

Por cierto, prefiero incluyendo el orden explícita por parte, ya que la mayoría de las bases de datos no ordenan los resultados de un grupo por. Mysql pasa a ser una base de datos que sí lo hace.

+0

En aras del rendimiento, debe aplicar las funciones a los valores de entrada (no a la columna de fecha) en la cláusula where de su subconsulta. –

+0

Además, el grupo ordena implícitamente los resultados, por lo que no es necesario realizar el pedido si ese es el orden que desea. –

+2

Esto parece ser cierto para mysql. ANSI SQL es bastante específico de que los grupos por resultados no están ordenados (aunque a menudo están en práctica). Espero que mysql sea lo suficientemente inteligente como para ignorar la cláusula "ordenar por" si no necesita hacer el trabajo. –

0
SELECT 
    HOUR(FROM_UNIXTIME(`date`)) AS `hour` 
    , COUNT(`id`) \ COUNT(DISTINCT TO_DAYS(`date`)) AS avgHourlyPostCount 
FROM fb_posts 
WHERE `date` > '2012-01-01' -- your optional date criteria 
GROUP BY hour 

Esto le da un recuento de todos los mensajes, dividido por el número de días, por horas .

Cuestiones relacionadas