2014-01-29 6 views
3

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

Набор данных выглядит следующим образом:

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), а продолжительность вызова записывается в поле (длительность) в секундах. Добавив секунды, сохраненные в поле (продолжительность) в поле (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 
+0

Всегда полезно, если вы предоставите данные образца. Какие поля имеют время начала и окончания вызова? –

+0

Время начала (calldate), а конечная дата должна быть рассчитана путем добавления продолжительности, которая хранится в секундах в поле (продолжительность) – user3246938

ответ

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 . Если более двух вызовов перекрываются, утомительно сортировать их
  • Теперь, поскольку ваши данные содержат числовой уникальный идентификатор, мы можем использовать его для фильтрации OSE дубликатами, трехкратном повторе и т.д. это делается с помощью AND a.uniqueid>b.uniqueid селектора и GROUP BY a.uniqueid, что делает только вызов с наименьшим UniqueID увидеть одновременных вызовов, то другие видят меньше
  • Использование MAX() на этом во внешнем запросе отфильтровывает эту запись
  • Нам нужно +1, чтобы получить количество пика вызовов: вызов с 2 одновременными вызовами означает пикового счетчик 3

SQLfiddle

+0

Спасибо за скрипт. Я думаю, что я могу уменьшить проблемы с производительностью, запустив ее в конце каждого дня и записывая результаты в таблицу. Таким образом, мне нужно всего лишь запустить запрос для данных за один день за один раз и может запускать дальнейшие отчеты о сохраненных результатах. – user3246938

+0

Я протестировал скрипт и получил следующую ошибку. # 1305 - ФУНКЦИЯ asteriskcdr.UNIX_TIMESTAM не существует. Возможно, мне нужно обратиться к таблице «cdr» – user3246938

+0

Извините, я вижу опечатку, теперь я отправил комментарий. Это выглядит хорошо. Он дает список чисел, соответствующих моим мыслям. однако на выходе не говорится, в какой день произошел пик. Было бы хорошо указать дату, затем пик для даты. Еще раз спасибо за этот рабочий скрипт. Сегодня я чему-то научился. – user3246938

0

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

1

Попробуйте добавить +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; 
Смежные вопросы