如何用CDR计算并发呼叫量

后端开发 2026-07-09

我有两个表

表testlist20230519_20

cdrid 开始时间 结束时间
641EA5F600041BC4 1684425611.337 1684425619.687
641EA5F600041BC5 1684425612 1684425618
641EA5F600041BC6 1684425610.082 1684425617.436
641EA5F600041BC7 1684425609.991 1684425616.000
641EA5F600041BC8 1684425608.965 1684425615.295
641EA5F600041BC9 1684425607.028 1684425614.436
641EA5F600041BCA 1684425606.106 1684425613.093
641EA5F600041BCB 1684425605.688 1684425612.922
641EA5F600041BCC 1684425604.455 1684425611.484
641EA5F600041BCD 1684425603.588 1684425610.809
641EA5F600041BCE 1684425602.389 1684425609.043
641EA5F600041BCF 1684425601.528 1684425608.633
641EA5F600041BD0 1684425612.363 1684425619.762
641EA5F600041BD1 1684425611.284 1684425618.075
641EA5F600041BD2 1684425610.130 1684425617.813
641EA5F600041BD3 1684425609.624 1684425616.611
641EA5F600041BD4 1684425608.071 1684425615.204
641EA5F600041BD5 1684425607.234 1684425615.559
641EA5F600041BD6 1684425606.055 1684425614.964
641EA5F600041BD7 1684425605.522 1684425613.368

表testtimestamp_10

|id |seconds              |cnt|cnt1|cnt2|cnt3|counted|counted2 |
|---|---------------------|---|----|----|----|-------|---------| 
|12 | 2023-05-19 00:00:11 | 0 | 0  | 0  |  0 |  0    |   0     |
|13 | 2023-05-19 00:00:12 | 0 | 0  | 0  |  0 |  0    |   0     |
|14 | 2023-05-19 00:00:13 | 0 | 0  | 0  |  0 |  0    |   0     |
|15 | 2023-05-19 00:00:14 | 0 | 0  | 0  |  0 |  0    |   0     |
|16 | 2023-05-19 00:00:15 | 0 | 0  | 0  |  0 |  0    |   0     |
|17 | 2023-05-19 00:00:16 | 0 | 0  | 0  |  0 |  0    |   0     |
|18 | 2023-05-19 00:00:17 | 0 | 0  | 0  |  0 |  0    |   0     |
|19 | 2023-05-19 00:00:18 | 0 | 0  | 0  |  0 |  0    |   0     |
|20 | 2023-05-19 00:00:19 | 0 | 0  | 0  |  0 |  0    |   0     |
|21 | 2023-05-19 00:00:20 | 0 | 0  | 0  |  0 |  0    |   0     |

我想按每秒对列 cnt 进行并发调用统计,像这样:

|id |seconds              |cnt|cnt1|cnt2|cnt3|counted|counted2 |
|---|---------------------|---|----|----|----|-------|---------| 
|12 | 2023-05-19 00:00:11 | 15| 0  | 0  |  0 |  0    |   0     |
|13 | 2023-05-19 00:00:12 | 16| 0  | 0  |  0 |  0    |   0     |
|14 | 2023-05-19 00:00:13 | 15| 0  | 0  |  0 |  0    |   0     |
|15 | 2023-05-19 00:00:14 | 13| 0  | 0  |  0 |  0    |   0     |
|16 | 2023-05-19 00:00:15 | 11| 0  | 0  |  0 |  0    |   0     |
|17 | 2023-05-19 00:00:16 | 8 | 0  | 0  |  0 |  0    |   0     |
|18 | 2023-05-19 00:00:17 | 6 | 0  | 0  |  0 |  0    |   0     |
|19 | 2023-05-19 00:00:18 | 4 | 0  | 0  |  0 |  0    |   0     |
|20 | 2023-05-19 00:00:19 | 2 | 0  | 0  |  0 |  0    |   0     |
|21 | 2023-05-19 00:00:20 | 0 | 0  | 0  |  0 |  0    |   0     |

我本来会创建一个存储过程,但速度非常慢,而一天有86400秒,通常需要大约12小时来计算,是否有更好的办法?

CREATE DEFINER=`root`@`%` PROCEDURE `test_procedure2`()
proc_label:BEGIN
declare sqlstring varchar(5412);
DECLARE a    int;
Declare b   varchar(256);
declare test     varchar(128);
DECLARE errno INT;
DECLARE done INT DEFAULT FALSE;

DECLARE cur1 CURSOR FOR SELECT id,unix_timestamp(seconds) as seconds FROM vms.testtimestamp_10;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
DECLARE EXIT HANDLER FOR SQLEXCEPTION

   -- set test = "OK2";
    select test;

 OPEN cur1;
  read_loop: LOOP
    FETCH cur1 INTO a, b;
    IF done THEN
      LEAVE read_loop;
    END IF;

 -- START TRANSACTION;
  -- set test = "OK3";
  -- select test;

    set sqlstring = concat("UPDATE vms.testtimestamp_10 " );
    set sqlstring = concat(sqlstring, "SET cnt = (SELECT count(*) FROM testlist20230519_20 WHERE ", b ,">= floor(starttime) and ",b," <= floor(endtime) )");
    set sqlstring = concat(sqlstring," where unix_timestamp(seconds) = ",b);
    set @d = sqlstring;
    PREPARE stmt from @d;
    EXECUTE stmt;
    DEALLOCATE PREPARE stmt;

-- COMMIT;

 END LOOP;
   select sqlstring;
  CLOSE cur1;

END

解决方案

我建议用一条查询来更新testtimestamp_10表,而不使用游标和循环。

with src as(
  SELECT id,count(cdrid) cnt
  FROM testtimestamp_10 t
  LEFT JOIN testlist20230519_20 d ON unix_timestamp(t.seconds) between d.starttime AND d.endtime
  GROUP BY id
)
UPDATE testtimestamp_10,src
  SET testtimestamp_10.cnt=src.cnt
WHERE testtimestamp_10.id=src.id
;

带数据的示例

在示例中,数据已被修改,因为你的示例中的表在时间上并不重叠。

对于MariaDb11及更早版本,请使用

UPDATE testtimestamp_10
JOIN (
  SELECT id, count(cdrid) cnt
  FROM testtimestamp_10 t
  LEFT JOIN testlist20230519_20 d ON unix_timestamp(t.seconds) between d.starttime and d.endtime
  GROUP BY id
) src ON testtimestamp_10.id=src.id
  SET testtimestamp_10.cnt=src.cnt
;

演示

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章