MySQL запрос - пик одновременных вызовов данных CDR

Привет, мне нужна помощь, чтобы понять, как рассчитать, сколько пиковых одновременных звонков у меня происходит в день из даты CDR, хранящейся в MySQL.

Набор данных выглядит так:

INSERT INTO `cdr` (`calldate`, `clid`, `src`, `dst`, `dcontext`, `channel`, `dstchannel`, 
                   `lastapp`, `lastdata`, `duration`, `billsec`, `disposition`, `amaflags`, 
                   `accountcode`, `uniqueid`, `userfield`) VALUES

Я могу использовать следующий запрос, чтобы вычислить количество записей на каждую уникальную дату.

SELECT COUNT(1) AS entries, date(calldate) AS DATE
FROM  `cdr` 
GROUP BY DATE (calldate)
LIMIT 0 , 1000

Однако это только говорит мне о теоретическом пике одновременных вызовов, а не фактическом пике.

Чтобы получить реальный пик, нам нужно сначала знать даты и время начала и окончания каждого звонка. В настоящее время дата и время начала записываются в поле (calldate), а продолжительность вызова записывается в поле (duration) в секундах. Добавляя секунды, хранящиеся в поле (duration), в поле (calldate) мы можем рассчитать время окончания.

Теперь, когда мы знаем время начала и окончания, нам нужно рассчитать, совпадают ли эти времена и сколько раз. Этот уровень SQL-запросов намного выше моих знаний.

Напомним, что я пытаюсь вычислить с запросом MySQL, какое максимальное количество одновременных вызовов из данных CDR, хранящихся в MySQL. Любая помощь с благодарностью получена

Пример данных:

    calldate,clid,src,dst,dcontext,channel,dstchannel,lastapp,lastdata,duration,billsec,disposition,amaflags,accountcode,uniqueid,userfield
08/11/2013 17:02,x,x,1000,default,x,x,x,x,26,26,ANSWERED,3,x,1383930162,x
08/11/2013 17:02,x,x,1000,default,x,x,x,x,24,24,ANSWERED,3,x,1383930164,x
08/11/2013 17:02,x,x,1000,default,x,x,x,x,45,45,ANSWERED,3,x,1383930146,x
08/11/2013 17:10,x,x,1000,default,x,x,x,x,2,2,ANSWERED,3,x,1383930649,x
08/11/2013 17:22,x,x,1000,default,x,x,x,x,4,4,ANSWERED,3,x,1383931380,x
08/11/2013 17:23,x,x,1000,default,x,x,x,x,5,5,ANSWERED,3,x,1383931388,x
08/11/2013 17:23,x,x,1000,default,x,x,x,x,9,9,ANSWERED,3,x,1383931395,x
10/11/2013 09:28,x,x,1000,default,x,x,x,x,7,7,ANSWERED,3,x,1384075689,x
10/11/2013 10:09,x,x,1000,default,x,x,x,x,57,57,ANSWERED,3,x,1384078181,x
10/11/2013 10:09,x,x,1000,default,x,x,x,x,81,81,ANSWERED,3,x,1384078164,x
10/11/2013 10:09,x,x,1000,default,x,x,x,x,102,102,ANSWERED,3,x,1384078143,x
11/11/2013 10:23,x,x,1000,default,x,x,x,x,3,3,ANSWERED,3,x,1384165439,x
11/11/2013 17:46,x,x,1000,default,x,x,x,x,30,30,ANSWERED,3,x,1384191975,x
11/11/2013 17:46,x,x,1000,default,x,x,x,x,30,30,ANSWERED,3,x,1384191976,x
11/11/2013 17:45,x,x,1000,default,x,x,x,x,50,50,ANSWERED,3,x,1384191956,x
11/11/2013 17:55,x,x,1000,default,x,x,x,x,9,9,ANSWERED,3,x,1384192544,x
13/11/2013 10:59,x,x,1000,default,x,x,x,x,209,209,ANSWERED,3,x,1384340382,x
13/11/2013 10:59,x,x,1000,default,x,x,x,x,230,230,ANSWERED,3,x,1384340361,x
13/11/2013 11:09,x,x,1000,default,x,x,x,x,1342,1342,ANSWERED,3,x,1384340963,x
13/11/2013 11:10,x,x,1000,default,x,x,x,x,1312,1312,ANSWERED,3,x,1384341009,x
13/11/2013 11:08,x,x,1000,default,x,x,x,x,1441,1441,ANSWERED,3,x,1384340891,x
13/11/2013 11:10,x,x,1000,default,x,x,x,x,1288,1288,ANSWERED,3,x,1384341059,x
13/11/2013 11:10,x,x,1000,default,x,x,x,x,1306,1306,ANSWERED,3,x,1384341050,x
13/11/2013 11:09,x,x,1000,default,x,x,x,x,1378,1378,ANSWERED,3,x,1384340990,x
13/11/2013 11:09,x,x,1000,default,x,x,x,x,1419,1419,ANSWERED,3,x,1384340953,x
13/11/2013 11:06,x,x,1000,default,x,x,x,x,1558,1558,ANSWERED,3,x,1384340815,x
13/11/2013 11:12,x,x,1000,default,x,x,x,x,1254,1254,ANSWERED,3,x,1384341121,x
13/11/2013 11:10,x,x,1000,default,x,x,x,x,1330,1330,ANSWERED,3,x,1384341045,x
13/11/2013 11:09,x,x,1000,default,x,x,x,x,1431,1431,ANSWERED,3,x,1384340947,x
13/11/2013 11:11,x,x,1000,default,x,x,x,x,1302,1302,ANSWERED,3,x,1384341076,x
13/11/2013 11:09,x,x,1000,default,x,x,x,x,1383,1383,ANSWERED,3,x,1384340995,x
13/11/2013 11:08,x,x,1000,default,x,x,x,x,1444,1444,ANSWERED,3,x,1384340937,x
13/11/2013 11:07,x,x,1000,default,x,x,x,x,1531,1531,ANSWERED,3,x,1384340850,x
13/11/2013 11:09,x,x,1000,default,x,x,x,x,1418,1418,ANSWERED,3,x,1384340963,x
13/11/2013 12:02,x,x,1000,default,x,x,x,x,10,10,ANSWERED,3,x,1384344169,x
13/11/2013 12:01,x,x,1000,default,x,x,x,x,807,807,ANSWERED,3,x,1384344072,x
13/11/2013 12:03,x,x,1000,default,x,x,x,x,680,680,ANSWERED,3,x,1384344200,x
13/11/2013 12:01,x,x,1000,default,x,x,x,x,793,793,ANSWERED,3,x,1384344090,x
13/11/2013 12:01,x,x,1000,default,x,x,x,x,772,772,ANSWERED,3,x,1384344111,x

3 ответа

Решение

Это должно работать, но это настоящий убийца производительности!

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

дает правильные ответы для вашего примера данных. Вот как это работает:

  • Самая внутренняя часть (a.calldate<=b.calldate AND (UNIX_TIMESTAMP(a.calldate)+a.duration)>=UNIX_TIMESTAMP(b.calldate)...) вычисляет пересечение: два вызова перекрываются, если начальная точка одного вызова находится в или после начальной точки другого вызова и в или до конечной точки этого вызова
  • Самостоятельное объединение таблиц вызовов находит все совпадения,
  • но с проблемой: самостоятельное соединение обнаруживает перекрытие между строками 1 и 2, а другое - со строками 2 и 1. Если перекрывается более двух вызовов, утомительно разбираться с этим
  • Теперь, поскольку ваши данные содержат уникальный уникальный числовой идентификатор, мы можем использовать его для фильтрации этих дубликатов, дубликатов и т. Д. AND a.uniqueid>b.uniqueid селектор и GROUP BY a.uniqueid, который делает только вызов с самым маленьким uniqueid, видит все одновременные вызовы, другие видят меньше
  • С помощью MAX() по этому во внешнем запросе отфильтровывает эту запись
  • Нам нужно +1 чтобы получить пиковое количество вызовов: вызов с 2 одновременными вызовами означает пиковое количество 3

SQLfiddle

Попробуйте добавить +1 для каждого начала вызова и -1 для каждого конца, а затем просто получить кумулятивную сумму этого столбца +1/-1
*** Преобразуйте calldate, если необходимо, или используйте ваш формат:

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;

Используя группы, попросите коммутатор записать общее количество вызовов до +1 в новое значение CDR для этой цели. так что вы знаете, сколько звонков было, когда последний звонок поступил в систему.

Другие вопросы по тегам