mysql query - peak concurrent calls CDR data

人盡茶涼 提交于 2019-12-01 08:07:05

This one should work, but is a real performance killer!

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

gives the correct answers for your example data. Here is, how it works:

  • The innermost part (a.calldate<=b.calldate AND (UNIX_TIMESTAMP(a.calldate)+a.duration)>=UNIX_TIMESTAMP(b.calldate)...) calculates the intersection: Two calls overlap, if the starting point of one call is at or after the starting point of the other call and at or before the ending point of that call
  • Self-joining the call tables finds all overlaps,
  • but with a problem: The self join finds an over lap between lines 1 and 2, but another one with lines 2 and 1. If more than two calls overlap, it is tedious to sort this out
  • Now since your data contains a numeric unique ID, we can use this to filter those duplicates, triplicates etc. this is done by the AND a.uniqueid>b.uniqueid selector and GROUP BY a.uniqueid, which makes only the call with the smallest uniqueid see all concurrent calls, the others see less
  • Using MAX() on this in the outer query filters out this record
  • We need the +1 to get the peak call count: A call with 2 concurrent calls means a peak count of 3

SQLfiddle

Try adding +1 for each start of call, and -1 for each end, then just get cumulative sum of that +1/-1 column
***Convert the calldate if needed or use your format:

set @from:='2015-02-01';
set @to:='2015-03-01';
set @csum:=0;
SELECT DT,CallCount, (@csum := @csum + CallCount) as cumulative_sum
FROM 
(select calldate AS DT, 1 AS CallCount
 from cdr
 where calldate between @from and @to

 union all

 select ADDDATE(calldate,INTERVAL duration SECOND) AS DT, -1 AS CallCount
 from cdr 
 where calldate between @from and @to
  ) Calls
ORDER BY 1 asc;

Using Groups, have the switch write the total calls up +1 to a new CDR value for such purpose. so you know how many calls were up when the last call entered the system.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!