количество однлвременных разговоров.
От: SergeyBi  
Дата: 21.07.05 09:50
Оценка:
Столкнулся по работе с реальной задачей, которую пока не совсем знаю как оптимально решить.

Ведется запись телефонных разговоров в call center. Есть таблица hystory в которую записываются данные о разговорах.
Среди прочих полей там есть время начала и окончания разговора. Телефонов, разговоры которых записываются довольно много.
Задача: определить максимальное количество одновременных разговоров за некоторый период времени(например 3 месяца).
Количество разговоров в неделю ~70 тыс.

У таблицы есть поле ID, которое проиндексировано. И записи с большей ID соответствует большее(точнее не меньшее) время начала разговора.


Заранее спасибо за варианты.
Re: количество однлвременных разговоров.
От: King Oleg Украина http://kingoleg.livejournal.com
Дата: 21.07.05 09:58
Оценка:
Здравствуйте, SergeyBi, Вы писали:

SB>Задача: определить максимальное количество одновременных разговоров за некоторый период времени(например 3 месяца).


В PostgreSQL можно построить соответствующий сложный индекс
King Oleg
*Читайте DOC'и, они rules*
Re[2]: количество однлвременных разговоров.
От: SergeyBi  
Дата: 21.07.05 10:03
Оценка:
KO>В PostgreSQL можно построить соответствующий сложный индекс

Все таки хотелось бы услышать решение "на пальцах".
Re: количество однлвременных разговоров.
От: Nev0 Россия  
Дата: 21.07.05 10:06
Оценка:
Здравствуйте, SergeyBi, Вы писали:

SB>Столкнулся по работе с реальной задачей, которую пока не совсем знаю как оптимально решить.


SB>Ведется запись телефонных разговоров в call center. Есть таблица hystory в которую записываются данные о разговорах.

SB>Среди прочих полей там есть время начала и окончания разговора. Телефонов, разговоры которых записываются довольно много.
SB>Задача: определить максимальное количество одновременных разговоров за некоторый период времени(например 3 месяца).
SB>Количество разговоров в неделю ~70 тыс.

SB>У таблицы есть поле ID, которое проиндексировано. И записи с большей ID соответствует большее(точнее не меньшее) время начала разговора.



SB>Заранее спасибо за варианты.

Подсчитываешь количество разговоров в начальный момент времени init_count.
Формируешь список моментов времени из моментов начала и конца разговоров, которые входят в нужный тебе период времени.
Сортируешь его.
Инициализируешь максимальное количество разговоров max_count = init_count
    и текущее количество разговоров count = init_count
Проходишь по этому списку {
    если момент времени - начало разговора
        count++
    если конец
        count--
    обновляем максимум: max_count = max(max_count, count);
}

max_count - результат
Re[2]: количество однлвременных разговоров.
От: SergeyBi  
Дата: 21.07.05 10:16
Оценка:
N>
N>Подсчитываешь количество разговоров в начальный момент времени init_count.
Можно считать что равно 0.

N>Формируешь список моментов времени из моментов начала и конца разговоров, которые входят в нужный тебе период времени.
N>Сортируешь его.
Считаем что у меня есть записи только из этого промежутка. Они отсортированы по времени начала разговора.

N>Инициализируешь максимальное количество разговоров max_count = init_count
N>    и текущее количество разговоров count = init_count
N>Проходишь по этому списку {
N>    если момент времени - начало разговора
N>        count++
N>    если конец
N>        count--
N>    обновляем максимум: max_count = max(max_count, count);
N>}

Вот тут я не понял. Что такое "момент времени" при обходе этого списка? Список содержит в себе записи у каждой есть время начала и окончания...

N>max_count - результат
N>
Re[3]: количество однлвременных разговоров.
От: Nev0 Россия  
Дата: 21.07.05 10:49
Оценка: 8 (2)
Здравствуйте, SergeyBi, Вы писали:


N>>
N>>Подсчитываешь количество разговоров в начальный момент времени init_count.
SB>Можно считать что равно 0.
N>>Формируешь список моментов времени из моментов начала и конца разговоров, которые входят в нужный тебе период времени.
N>>Сортируешь его.
SB>Считаем что у меня есть записи только из этого промежутка. Они отсортированы по времени начала разговора.

Но концы не отсортированы Можно конечно отсортировать только концы разговоров и потом слить списки началов и концов. Нам важно получить список моментов времени, когда изменяется количество подключений.
N>>Инициализируешь максимальное количество разговоров max_count = init_count
N>>    и текущее количество разговоров count = init_count
N>>Проходишь по этому списку {
N>>    если момент времени - начало разговора
N>>        count++
N>>    если конец
N>>        count--
N>>    обновляем максимум: max_count = max(max_count, count);
N>>}

SB>Вот тут я не понял. Что такое "момент времени" при обходе этого списка? Список содержит в себе записи у каждой есть время начала и окончания...

N>>max_count - результат
N>>
Re: количество однлвременных разговоров.
От: pivoo Россия  
Дата: 21.07.05 10:51
Оценка:
s[] - массив начал разговоров
e[] - массив окончаний разговоров
n - количество разговоров
minE - того же типа что и время в массивах

int maxC=0;
for(int i=0; i<n; i++)
{
   minE = e[i]
   int c = 1;
   for(int j=i+1; ;j++)
   {
      if( s[j]>minE )
        break;
      c++;
      minE = min( e[i], e[j] );
   }
   if (c>maxC)
     maxC = c;
}

maxC - ответ



вроде так
Re[2]: количество однлвременных разговоров.
От: Nev0 Россия  
Дата: 21.07.05 11:10
Оценка:
Здравствуйте, pivoo, Вы писали:


P>
P>s[] - массив начал разговоров
P>e[] - массив окончаний разговоров
P>n - количество разговоров
P>minE - того же типа что и время в массивах

P>int maxC=0;
P>for(int i=0; i<n; i++)
P>{
P>   minE = e[i]
P>   int c = 1;
P>   for(int j=i+1; ;j++)
P>   {
P>      if( s[j]>minE )
P>        break;
P>      c++;
P>      minE = min( e[i], e[j] );
P>   }
P>   if (c>maxC)
P>     maxC = c;
P>}

P>maxC - ответ
P>



P>вроде так


Неправильно и неоптимально
вот простой тест:
1 8
2 3
4 7
5 6

Выдает 2, хотя на промежутке 5-6 3 соединения. Да и работает O(N^2), когда в моем варианте самой тяжелой операцией является сортировка, которая во всех языках реализована за O(NlogN).
Re[3]: количество однлвременных разговоров.
От: pivoo Россия  
Дата: 21.07.05 11:50
Оценка:
Здравствуйте, Nev0, Вы писали:

N>Неправильно и неоптимально

N>вот простой тест:
N>
N>1 8
N>2 3
N>4 7
N>5 6
N>

N>Выдает 2, хотя на промежутке 5-6 3 соединения. Да и работает O(N^2), когда в моем варианте самой тяжелой операцией является сортировка, которая во всех языках реализована за O(NlogN).

Насчет сложности — предыдущий вариант сложность не N^2 , a N*c, где с < среднего количества одновременных разговоров.

Согласен, не правильно, если изменить, вроде должно заработать, вот здесь уже сложность N^2? если не больше


int maxC=0;
for(int i=0; i<n; i++)
{
   minE = e[i]
   int c = 1;
   for(int j=0; ;j++)
   {
      if( s[j]>minE || (s[i]<s[j] && e[i]>s[j]) )
        break;
      c++;
      minE = min( e[i], e[j] );
   }
   if (c>maxC)
     maxC = c;
}
Re[2]: количество однлвременных разговоров.
От: pivoo Россия  
Дата: 21.07.05 11:54
Оценка:
если честно, алгоритма не понял
это случайно не количество незавершившихся звонков на момент окончания контрольного времени получается ?
Re[3]: количество однлвременных разговоров.
От: pivoo Россия  
Дата: 21.07.05 12:02
Оценка:
Здравствуйте, pivoo, Вы писали:

P>если честно, алгоритма не понял

P>это случайно не количество незавершившихся звонков на момент окончания контрольного времени получается ?

сори, все отсек
не заметил одной строки
Re[4]: количество однлвременных разговоров.
От: SergeyBi  
Дата: 21.07.05 12:18
Оценка:
N>Но концы не отсортированы Можно конечно отсортировать только концы разговоров и потом слить списки началов и концов. Нам важно получить список моментов времени, когда изменяется количество подключений.

Я все понял. Отличная идея. Сначала недооценил. Действительно остается только отсортировать время окончания.
Кстати, а как проще всего посчитать среднее колличество(по времени) одновременных разговоров?


Приходит в голову мысль посчитать сумарное время разговоров и поделить эт на реальное время.
Re: количество однлвременных разговоров.
От: tavr  
Дата: 21.07.05 12:29
Оценка:
Здравствуйте, SergeyBi, Вы писали:

SB>Столкнулся по работе с реальной задачей, которую пока не совсем знаю как оптимально решить.


SB>Ведется запись телефонных разговоров в call center. Есть таблица hystory в которую записываются данные о разговорах.

SB>Среди прочих полей там есть время начала и окончания разговора. Телефонов, разговоры которых записываются довольно много.
SB>Задача: определить максимальное количество одновременных разговоров за некоторый период времени(например 3 месяца).
SB>Количество разговоров в неделю ~70 тыс.

SB>У таблицы есть поле ID, которое проиндексировано. И записи с большей ID соответствует большее(точнее не меньшее) время начала разговора.


Я так понимаю от тебя требуют статистику за определенный период и максимальная загрузка — одна из форм отчетности
Может имеет смысл завести еще одну таблицу, куда можно перегнать данные из history в виде
время — количество звонков в это время

для этого выбираешь оптимальный временной промежуток, скажем 5 минут и подсчитываешь количество запросов в эти 5 минут:
2005-06-01 18:00        21
2005-06-01 18:05        19
2005-06-01 18:10        26


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

если в history пишется ~10 тыс записей в сутки, то в эту базу попадет 288 записей (для 5-мин. интервала), что гораздо быстрее обработать

SB>Заранее спасибо за варианты.

Re: количество однлвременных разговоров.
От: wildwind Россия  
Дата: 21.07.05 12:34
Оценка:
Здравствуйте, SergeyBi, Вы писали:

SB>Задача: определить максимальное количество одновременных разговоров за некоторый период времени(например 3 месяца).


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

Для эффективного поиска надо создать такой индекс: (start, end, ID). Для каждого момента времени делаем запрос:
select count(ID) from history
 where :time between start and end
   and start <= :time - :max_duration
где max_duration — максимальная продолжительность разговора, которую надо посчитать заранее. И считаем максимум. Для скорости все это лучше делать в хранимой процедуре, если СУБД позволяет. Кстати, какая СУБД?
Для еще большей скорости можно взять интервал не в секунду, а больше, скажем 5 секунд. Со всеми вытекающими.
Re[2]: количество однлвременных разговоров.
От: SergeyBi  
Дата: 21.07.05 13:48
Оценка:
Здравствуйте, wildwind, Вы писали:
SB>>Задача: определить максимальное количество одновременных разговоров за некоторый период времени(например 3 месяца).

W>Полагаю, время в таблице хранится с точностью до секунд? Вот и надо для каждой секунды в интересующем нас периоде подсчитать количество одновременных разговоров, а потом взять максимум.


W>Для эффективного поиска надо создать такой индекс: (start, end, ID). Для каждого момента времени делаем запрос:

W>
W>select count(ID) from history
W> where :time between start and end
W>   and start <= :time - :max_duration
W>
где max_duration — максимальная продолжительность разговора, которую надо посчитать заранее. И считаем максимум. Для скорости все это лучше делать в хранимой процедуре, если СУБД позволяет. Кстати, какая СУБД?

W>Для еще большей скорости можно взять интервал не в секунду, а больше, скажем 5 секунд. Со всеми вытекающими.

В общем-то правильно. Думаю с таким индексом сложность задачи будет примерно N*log(N). Но в этой ветке было предложено решение без индекса, с как максимум такой же сложностью А минимум с линейной(если индекс на время добавить).
Re[2]: количество однлвременных разговоров.
От: pivoo Россия  
Дата: 21.07.05 13:58
Оценка:
Здравствуйте, wildwind, Вы писали:

W>Здравствуйте, SergeyBi, Вы писали:


SB>>Задача: определить максимальное количество одновременных разговоров за некоторый период времени(например 3 месяца).


W>Полагаю, время в таблице хранится с точностью до секунд? Вот и надо для каждой секунды в интересующем нас периоде подсчитать количество одновременных разговоров, а потом взять максимум.


W>Для эффективного поиска надо создать такой индекс: (start, end, ID). Для каждого момента времени делаем запрос:

W>
W>select count(ID) from history
W> where :time between start and end
W>   and start <= :time - :max_duration
W>
где max_duration — максимальная продолжительность разговора, которую надо посчитать заранее. И считаем максимум. Для скорости все это лучше делать в хранимой процедуре, если СУБД позволяет. Кстати, какая СУБД?

W>Для еще большей скорости можно взять интервал не в секунду, а больше, скажем 5 секунд. Со всеми вытекающими.

а если расчетный период — месяц ?
Re[3]: количество однлвременных разговоров.
От: wildwind Россия  
Дата: 21.07.05 14:12
Оценка:
Здравствуйте, SergeyBi, Вы писали:

SB>В общем-то правильно. Думаю с таким индексом сложность задачи будет примерно N*log(N).

Так какая СУБД? Для некоторых можно оптимизировать...
Re[3]: количество однлвременных разговоров.
От: wildwind Россия  
Дата: 21.07.05 14:13
Оценка:
Здравствуйте, pivoo, Вы писали:

P>а если расчетный период — месяц ?

И что?
Re[4]: количество однлвременных разговоров.
От: SergeyBi  
Дата: 21.07.05 14:23
Оценка:
Здравствуйте, wildwind, Вы писали:

W>Здравствуйте, SergeyBi, Вы писали:


SB>>В общем-то правильно. Думаю с таким индексом сложность задачи будет примерно N*log(N).

W>Так какая СУБД? Для некоторых можно оптимизировать...

ms sql 2000
Re[4]: количество однлвременных разговоров.
От: SergeyBi  
Дата: 21.07.05 14:24
Оценка:
W>И что?

Боюсь что если сделать 3-4 запроса — это одно, то сделать порядка 10^6 запросов к базе — это смерть.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.