来自CDR的同时呼叫

时间:2008-09-08 20:21:36

标签: sql language-agnostic asterisk

当只有每个事件的开始时间和持续时间时,我需要对simultaneousus事件进行分析。

详情

我有一个标准的CDR呼叫详细记录,其中包含:

  • calldate(每次通话开始的时间日期
  • 持续时间(int,呼叫持续时间的秒数)
  • 频道(字符串)

我需要提出的是在给定的时间段内每秒对同时调用进行某种分析。例如,我们昨天同时打电话的图表。

(问题是相同的,如果我们在网站上有持续时间的访问者日志,并希望获得一组网页的同时客户端)

你的算法是什么?

我可以在给定时间段内迭代记录,并填充一个数组,其中数组的每个桶在整个时间段内对应于1秒。这可行并且似乎很快,但如果时间段很长(比如说... 1年),我需要大量内存(3600x24x365x4字节~120MB aprox)。

这适用于基于网络的交互式应用,所以我的内存占用空间应该足够小。

修改

同时,我指的是给定秒钟的所有呼叫。第二个是我的最小单位。我不能使用更大的东西(例如小时),因为一小时内所有的电话都不需要同时举行。

4 个答案:

答案 0 :(得分:1)

我会在数据库上实现这个。使用带有DATEPART的GROUP BY子句,您可以获得所需时间段的同时呼叫列表,包括秒,分钟,小时等等。

在网络方面,您只需显示查询返回的直方图。

答案 1 :(得分:0)

@ eric-z-beard:我真的希望能够在数据库上实现这一点。我喜欢你的提议,虽然它似乎导致某些事情,但我并不完全理解它。你能详细说说吗?请回想一下,每次通话都会持续几秒钟,每一秒都需要计算。如果使用DATEPART(或类似MySQL的东西),那么GROUP BY应该使用什么秒。见同时注释。

对此进行阐述,我找到了一种使用临时表解决它的方法。假设temp保持从tStart到tEnd的所有秒数,我可以做

SELECT temp.second, count(call.id)
FROM call, temp
WHERE temp.second between (call.start and call.start + call.duration)
GROUP BY temp.second

然后,按照建议,网络应用程序应将其用作直方图。

答案 2 :(得分:0)

你可以使用静态Numbers表来处理很多像这样的SQL技巧。 Numbers表只包含从0到n的整数,对于n,如10000。

然后你的临时表永远不需要创建,而是一个子查询,如:

SELECT StartTime + Numbers.Number AS Second
FROM Numbers

答案 3 :(得分:0)

您可以使用3个字段创建表格'simultaneous_calls'

yyyymmdd  Char(8),
day_second Number,  -- second of the day,
count          Number   -- count of simultaneous calls
您的Web服务可以从此表中获取“计数”值并进行一些统计。

Simultaneous_calls表将由一些批处理程序填充,该程序将在每天结束后每天启动。

假设您使用Oracle,批处理可能会启动PL / SQL过程,该过程执行以下操作:

  1. 为每天的每一秒附加24 * 3600 = 86400条记录的表格,默认“count”值= 0。
  2. 为查询定义'day_cdrs'光标:
  3. 
    Select to_char(calldate, 'yyyymmdd')              yyyymmdd,
             (calldate - trunc(calldate)) * 24 * 3600   starting_second,
             duration                                              duration
    From cdrs
    Where cdrs.calldate >= Trunc(Sysdate -1)
        And cdrs.calldate 
    1. Iterates the cursor to increment 'count' field for the seconds of the call:
    For cdr in day_cdrs
    Loop 
       Update simultaneos_calls
       Set      count = count + 1
       Where yyyymmdd = cdr.yyyymmdd
           And day_second Between cdr.starting_second And cdr.starting_second + cdr.duration;
    End Loop;