2011-10-25 20 views
7

Tengo una tabla MySQL con llamadas telefónicas. Cada fila significa una llamada telefónica. Las columnas son:Datos MySQL - Contar el número de llamadas telefónicas al mismo tiempo

start_time 
start_date 
duration 

que necesita para obtener un máximo de llamadas telefónicas llamadas al mismo tiempo. Es por el dimensionamiento de la central telefónica.

Mi solución es crear dos columnas timestamp timestamp_start y timestamp_end. Luego ejecutar un segundo bucle por segundo, día a día y pido MySQL algo como:

SELECT Count(*) FROM tbl WHERE start_date IN (thisday, secondday) AND "this_second_checking" BETWEEN timestamp_start AND timestamp_end; 

Es bastante lento. ¿Existe una solución mejor? ¡Gracias!

EDITAR - Utilizo esta solución y me da los resultados adecuados. Se utiliza la capa SQL dibi - http://dibiphp.com/cs/quick-start.

$starts = dibi::query("SELECT ts_start, ts_end FROM " . $tblname . " GROUP BY ts_start"); 
if(count($starts) > 0): 
    foreach ($starts as $row) { 
    if(isset($result)) unset($result); 
    $result = dibi::query('SELECT Count(*) FROM ' . $tblname . ' WHERE "'.$row->ts_start.'" BETWEEN ts_start AND ts_end'); 
    $num = $result->fetchSingle(); 
    if($total_max < $num): 
     $total_max = $num; 
    endif;  
    } 
endif; 
echo "Total MAX: " . $total_max; 
+0

solo necesita comprobar cuando se inicia una nueva llamada para saber cuántas se están ejecutando, no es necesario verificar cada segundo – Blem

+0

¿Tiene índices en start_date, timestamp_start y timestamp_end? – pgl

+0

Sí, tengo índices. Fue una gran mejora. Blem: ¡Lo pienso, gracias! – Xdg

Respuesta

5

En lugar de ejecutarlo segundo por segundo, debe ver por cada fila (llamada telefónica) qué otras llamadas telefónicas estaban activas en ese momento. Después de eso, agrupa todos los resultados por ID de la fila y verifica cuál tiene el recuento máximo. Básicamente, algo como esto:

SELECT MAX(calls.count) 
FROM (
    SELECT a.id, COUNT(*) AS count 
    FROM tbl AS a 
    INNER JOIN tbl AS b ON (
     (b.timestamp_start BETWEEN a.timestamp_start AND a.timestamp_end) 
     OR 
     (b.timestamp_end BETWEEN a.timestamp_start AND a.timestamp_end) 
    ) 
    GROUP BY a.id 
) AS calls 

Crear un índice en las columnas de marca de tiempo también ayudará.

+0

Eres un poco más rápido que yo :) +1 – Nemoden

+0

Esto no me da los mismos resultados, como mi primer algoritmo. Tal vez tengo algún error en mi programa. Lo reviso en las próximas 3 horas. – Xdg

+0

Las marcas de tiempo incluyen la parte de fecha, no solo la hora, ¿verdad? De lo contrario, deberían hacerlo, de esa manera no es necesario que verifique por separado las columnas de fecha y hora. –

-1

¿Qué tal:

SELECT MAX(callCount) FROM (SELECT COUNT(duration) AS callCount, CONCAT(start_date,start_time) AS callTime FROM tbl GROUP BY callTime) 

que le daría el número máximo de llamadas en un solo "tiempo". Suponiendo start_date y start_time son cadenas. Si son tiempos enteros, probablemente podrías optimizarlo de alguna manera.

+0

'CONCAT (start_date, start_time) AS callTime FROM tbl GROUP BY callTime' -' Eso le daría el número máximo de llamadas en un solo "tiempo" .' - ¿En serio? o_O Las fechas de concatenación y la agrupación por concatuación no tienen sentido para mí con el fin de resolver este problema ... – Nemoden

+0

Agruparía todos los tiempos idénticos, sin embargo, veo su punto ahora: no se superponen duraciones de tiempo, solo tiempos de inicio simultáneos. Disculpas –

Cuestiones relacionadas