Mysql
 sql >> Database >  >> RDS >> Mysql

query mysql - picco di dati CDR per chiamate simultanee

Questo dovrebbe funzionare, ma è un vero killer di prestazioni!

SELECT
  calldate,
  MAX(concurrent)+1 AS peakcount
FROM (
    SELECT
      DATE(a.calldate) as calldate,
      COUNT(b.uniqueid) AS concurrent
    FROM cdr AS a, cdr AS b
    WHERE  
      a.calldate BETWEEN '2013-11-08 00:00:00' AND '2013-11-13 23:59:59'
      AND (
        (a.calldate<=b.calldate AND (UNIX_TIMESTAMP(a.calldate)+a.duration)>=UNIX_TIMESTAMP(b.calldate))
        OR (b.calldate<=a.calldate AND (UNIX_TIMESTAMP(b.calldate)+b.duration)>=UNIX_TIMESTAMP(a.calldate))
      )
      AND a.uniqueid>b.uniqueid
    GROUP BY a.uniqueid
  ) AS baseview
GROUP BY calldate

fornisce le risposte corrette per i tuoi dati di esempio. Ecco come funziona:

  • La parte più interna (a.calldate<=b.calldate AND (UNIX_TIMESTAMP(a.calldate)+a.duration)>=UNIX_TIMESTAMP(b.calldate) ...) calcola l'intersezione:due chiamate si sovrappongono, se il punto di inizio di una chiamata è al o dopo il punto di inizio dell'altra chiamata e al o prima del punto di fine di quella chiamata
  • L'auto-unione delle tabelle delle chiamate trova tutte le sovrapposizioni,
  • ma con un problema:il self join trova un over lap tra le righe 1 e 2, ma un altro con le righe 2 e 1. Se più di due chiamate si sovrappongono, è noioso risolverlo
  • Ora, poiché i tuoi dati contengono un ID numerico univoco, possiamo usarlo per filtrare quei duplicati, triplicati ecc. Questo viene fatto da AND a.uniqueid>b.uniqueid selettore e GROUP BY a.uniqueid , che fa in modo che solo la chiamata con il più piccolo uniqueid veda tutte le chiamate simultanee, le altre vedano meno
  • Utilizzo di MAX() su questo nella query esterna filtra questo record
  • Ci serve il +1 per ottenere il numero massimo di chiamate:una chiamata con 2 chiamate simultanee significa un numero massimo di 3

SQLfiddle