使用MySQL计算并发调用

时间:2018-02-19 21:59:59

标签: mysql

我正在尝试计算MySQL中的并发调用。我的表格中的列是开始时间结束时间 ID 。按原样使用时间字段,我能够查询返回Starttime并发调用次数的查询。当我尝试将时间字段转换为最近的分钟时,我得到的计数不正确。我已经开发出一种解决方案,可以在四舍五入到最接近的分钟时获得正确的计数,但是如果感觉既不清晰也不高效

这是我的表:

create table `test_table4` (
`Starttime` DATETIME default null,
`Endtime` DATETIME  default null,
`ID` varchar(20)
) ENGINE=MyISAM AUTO_INCREMENT=4 DEFAULT CHARSET=latin1; 

insert into `test_table4` (`Starttime`, `Endtime`, `ID`) VALUES ('2006-12-30 08:03:02', '2006-12-30 08:03:04', 'A');
insert into `test_table4` (`Starttime`, `Endtime`, `ID`) VALUES ('2006-12-30 08:33:02', '2006-12-30 08:37:45', 'B');
insert into `test_table4` (`Starttime`, `Endtime`, `ID`) VALUES ('2006-12-30 08:33:02', '2006-12-30 08:33:05', 'C');
insert into `test_table4` (`Starttime`, `Endtime`, `ID`) VALUES ('2006-12-30 08:33:06', '2006-12-30 08:37:44', 'C');
insert into `test_table4` (`Starttime`, `Endtime`, `ID`) VALUES ('2006-12-30 08:40:21', '2006-12-30 08:41:25', 'D');
insert into `test_table4` (`Starttime`, `Endtime`, `ID`) VALUES ('2006-12-30 08:40:21', '2006-12-30 08:41:25', 'E');
insert into `test_table4` (`Starttime`, `Endtime`, `ID`) VALUES ('2006-12-30 08:47:00', '2006-12-30 08:47:47', 'F');
insert into `test_table4` (`Starttime`, `Endtime`, `ID`) VALUES ('2006-12-30 08:56:01', '2006-12-30 08:56:01', 'G');
insert into `test_table4` (`Starttime`, `Endtime`, `ID`) VALUES ('2006-12-30 08:56:01', '2006-12-30 08:56:04', 'H');
insert into `test_table4` (`Starttime`, `Endtime`, `ID`) VALUES ('2006-12-30 08:56:07', '2006-12-30 08:57:37', 'I');
insert into `test_table4` (`Starttime`, `Endtime`, `ID`) VALUES ('2006-12-30 08:56:07', '2006-12-30 08:57:35', 'J');
insert into `test_table4` (`Starttime`, `Endtime`, `ID`) VALUES ('2006-12-30 08:56:28', '2006-12-30 08:56:41', 'K');
insert into `test_table4` (`Starttime`, `Endtime`, `ID`) VALUES ('2006-12-30 08:56:28', '2006-12-30 08:56:41', 'L');
insert into `test_table4` (`Starttime`, `Endtime`, `ID`) VALUES ('2006-12-30 08:57:08', '2006-12-30 08:57:24', 'M');
insert into `test_table4` (`Starttime`, `Endtime`, `ID`) VALUES ('2006-12-30 08:57:09', '2006-12-30 08:57:24', 'N');
insert into `test_table4` (`Starttime`, `Endtime`, `ID`) VALUES ('2006-12-30 08:58:02', '2006-12-30 08:58:02', 'O');
insert into `test_table4` (`Starttime`, `Endtime`, `ID`) VALUES ('2006-12-30 08:58:59', '2006-12-30 08:59:59', 'R');
insert into `test_table4` (`Starttime`, `Endtime`, `ID`) VALUES ('2006-12-30 08:58:59', '2006-12-30 08:59:58', 'Q');
insert into `test_table4` (`Starttime`, `Endtime`, `ID`) VALUES ('2006-12-30 09:00:34', '2006-12-30 09:00:35', 'S');
insert into `test_table4` (`Starttime`, `Endtime`, `ID`) VALUES ('2006-12-30 09:00:55', '2006-12-30 09:02:55', 'T');
insert into `test_table4` (`Starttime`, `Endtime`, `ID`) VALUES ('2006-12-30 09:01:27', '2006-12-30 09:01:28', 'U');
insert into `test_table4` (`Starttime`, `Endtime`, `ID`) VALUES ('2006-12-30 09:02:18', '2006-12-30 09:02:18', 'V');

要按原样使用Starttime获取并发调用的数量,请运行以下查询。

select c1.Starttime, count(distinct c2.ID)
from test_table4 c1
left join test_table4 c2
on c1.Starttime between c2.Starttime and
c2.Endtime AND c2.Endtime IS NOT NULL
group by c1.Starttime;

这给了我正确的答案。注意ID C进行两次调用。当我将开始时间和结束时间投射到最近的分钟并获得计数时,这会导致我的分析出错。

select FROM_UNIXTIME(CEILING(UNIX_TIMESTAMP(c1.starttime)/60)*60) as Date_Truncated, count(distinct c2.ID) as all_calls
from test_table4 c1 
left join test_table4 c2 
on FROM_UNIXTIME(CEILING(UNIX_TIMESTAMP(c1.starttime)/60)*60)
between FROM_UNIXTIME(CEILING(UNIX_TIMESTAMP(c2.starttime)/60)*60) and 
FROM_UNIXTIME(CEILING(UNIX_TIMESTAMP(c2.Endtime)/60)*60)    
and c2.Endtime is not null
GROUP BY Date_Truncated;

查询返回8:34有两个调用,但实际上有三个,因为C进行两次调用 - 一个在8:33:02和8:33:06,所以与ID B一起,在8:33之后的8:34三次通话时:B和C的xx到最近的分钟。

否则我必须运行distinct count c2.ID,因为正在运行count c2.ID会返回不准确的计数。我提出了一个解决方案,但感觉不够优雅和低效。

select final_data.Date_Truncated, final_data.all_calls/final_data.row_count as concurrent_calls_count
from
(select *
from
(select FROM_UNIXTIME(CEILING(UNIX_TIMESTAMP(c1.starttime)/60)*60) as Date_Truncated, count(c2.ID) as all_calls
from test_table4 c1 
left join test_table4 c2 
on FROM_UNIXTIME(CEILING(UNIX_TIMESTAMP(c1.starttime)/60)*60)
between FROM_UNIXTIME(CEILING(UNIX_TIMESTAMP(c2.starttime)/60)*60) and 
FROM_UNIXTIME(CEILING(UNIX_TIMESTAMP(c2.Endtime)/60)*60)
and c2.Endtime is not null
GROUP BY Date_Truncated) t1
left join
(select FROM_UNIXTIME(CEILING(UNIX_TIMESTAMP(Starttime)/60)*60) as    Date_Truncated2, count(*) as row_count
from test_table4
group by  Date_Truncated2) t2
on t1.Date_Truncated = t2.Date_Truncated2) final_data;

是否有更简单或更好的方法来计算我错过的并发呼叫?

0 个答案:

没有答案