Mysql 获取连续记录视图的持续时间
我有一个小部件销售人员的通话记录。记录客户记录中的每次单击。员工一天可以多次访问同一个客户帐户,因此在一天的不同时间,可能会有几十次连续的点击聚集在同一个recordID下 例如:Mysql 获取连续记录视图的持续时间,mysql,datetime,select,optimization,gaps-and-islands,Mysql,Datetime,Select,Optimization,Gaps And Islands,我有一个小部件销售人员的通话记录。记录客户记录中的每次单击。员工一天可以多次访问同一个客户帐户,因此在一天的不同时间,可能会有几十次连续的点击聚集在同一个recordID下 例如: recordID userID date_event 33450 321 2013-06-20 16:22:02 33450 321 2013-06-20 16:22:02 33450 321 2013-06-20 16:22:24 33450 321 2013
recordID userID date_event
33450 321 2013-06-20 16:22:02
33450 321 2013-06-20 16:22:02
33450 321 2013-06-20 16:22:24
33450 321 2013-06-20 16:22:24
22222 321 2013-06-20 16:22:53
22222 321 2013-06-20 16:22:54
12345 321 2013-06-20 16:23:43
12345 321 2013-06-20 16:23:44
12345 321 2013-06-20 16:24:00
12345 321 2013-06-20 16:24:05
12345 321 2013-06-20 16:24:05
12345 321 2013-06-20 18:16:09
12345 321 2013-06-20 18:16:09
33450 321 2013-06-20 18:33:24
33450 321 2013-06-20 18:35:11
33450 321 2013-06-20 18:36:55
12345 321 2013-06-20 19:01:14
98765 321 2013-06-20 19:02:43
在上面的数据集中,我有6组访问权限
first last duration(seconds)
33450 2013-06-20 16:22:02 2013-06-20 16:22:24 22
22222 2013-06-20 16:22:30 2013-06-20 16:22:54 24
12345 2013-06-20 16:23:43 2013-06-20 18:16:09 6746
33450 2013-06-20 18:33:24 2013-06-20 18:36:55 211
12345 2013-06-20 19:01:14 2013-06-20 19:01:14 0
98765 2013-06-20 19:02:43 2013-06-20 19:02:43 0
持续时间是指眼睛注视记录的估计时间,而不是实际时间。我无法检测员工何时积极使用此应用程序,或何时使用客户端工具在其他应用程序或网站中查找数据
表格结构为:
CREATE TABLE IF NOT EXISTS `record_log` (
`event_id` int(11) NOT NULL AUTO_INCREMENT,
`userID` int(5) DEFAULT NULL,
`recordID` int(10) DEFAULT NULL,
`date_event` datetime DEFAULT NULL,
PRIMARY KEY (`event_id`),
KEY `userID` (`userID`),
KEY `date_event` (`date_event`),
KEY `recordID` (`recordID`),
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
构造查询以返回第二个数据集的最佳方法是什么?这可以在一个查询中完成而不使用太多的周期吗?在给定的一天中,我可能会访问数千条记录 是的,可以返回指定的结果集,但这并不完美。特别是,使用内联视图(MySQL称之为“派生表”)意味着这些行将被写入一个临时MyISAM表,并且对于大型集合来说,操作可能会很昂贵,因此使用这种方法获得性能可能需要在最内部的查询上使用一些谓词来获得大小合理的数据集。。。e、 g
WHERE q.userID = 321
AND q.date_event >= '2012-01-01'
AND q.date_event < '2012-01-02'
我将使用带有变量的SQL查询:
SELECT
recordID,
userID,
MIN(date_event) first,
MAX(date_event) last,
TIME_TO_SEC(TIMEDIFF(MAX(date_event), MIN(date_event))) sec
FROM (
SELECT
events.*,
CASE WHEN @last_recordID=recordID THEN @grp ELSE @grp:=@grp+1 END groupID,
@last_recordID := recordID
FROM
events, (SELECT @grp:=0, @last_recordID:=NULL) r
ORDER BY
event_ID
) s
GROUP BY
recordID,
userID,
groupID
ORDER BY
groupID
请参阅fiddle。返回数据集的最简单查询是:
SELECT recordID, MIN(date_event) AS `first`, MAX(date_event) AS `last`
, TIMESTAMPDIFF(SECOND, MIN(date_event), MAX(date_event)) AS `duration(seconds)`
FROM `record_log`
GROUP BY recordID
另一个可能更快的选择是,每次访问客户记录时,只需计算出合理的持续时间估计。以下查询每次访问使用30秒的持续时间:
SELECT recordID, COUNT(*) AS staff_clicks, 30*COUNT(*) AS `estimated duration(seconds)`
FROM `record_log`
GROUP BY recordID
这些都是非常基本的,但它们确实回答了您最初的问题。有很多选择,但如果没有更多信息(时间限制、所需的准确度等),很难知道该开什么药。您有自动增量ID吗?您的记录是如何组合在一起的?当记录id发生变化时,组会发生变化?是-自动增量为“事件id”。记录将按recordID分组,但关键是我需要的不仅仅是给定时间段内每个recordID的所有持续时间的简单总和。一天中可以多次访问同一个recordID。通常会有一组连续的活动。或者,recordID可能在一天中只被访问过一次。我试着在上面的数据中解释和展示这一点。快速跟进。为什么使用
q.date\u event>='2012-01-01'和q.date\u event<'2012-01-02'
而不是date(q.date\u event)='2012-01-01'
?好问题。在谓词(WHERE子句)中,我们不希望在函数中包装列,因为这样做会禁用列上的索引来满足查询。对于裸列上的范围,可以使用索引。但是如果我们使用DATE(q.DATE\u event)
,那么这将有效地迫使MySQL为表中的每一行计算表达式(即调用DATE函数)。(实际上,这是最糟糕的情况;如果行首先被另一个谓词过滤掉,那么MySQL可以跳过对已经过滤掉的行的表达式求值。)这确实是一个更简单的查询。不幸的是,它没有返回指定的结果集。例如,对于recordID 33450,它将返回一行,其持续时间为2013-06-20 16:22:02
-2013-06-20 18:36:55
,而不是规范中所示的两个单独的持续时间。
SELECT recordID, MIN(date_event) AS `first`, MAX(date_event) AS `last`
, TIMESTAMPDIFF(SECOND, MIN(date_event), MAX(date_event)) AS `duration(seconds)`
FROM `record_log`
GROUP BY recordID
SELECT recordID, COUNT(*) AS staff_clicks, 30*COUNT(*) AS `estimated duration(seconds)`
FROM `record_log`
GROUP BY recordID