我有 Widget 销售人员的通话记录。客户记录中的每次点击都会被记录。工作人员每天可能会多次访问同一客户帐户,因此一天中不同时间同一 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-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 ;
构造查询以返回第二个数据集的最佳方法是什么?是否可以在一个查询中完成此操作而不使用太多循环?在某一天我可能会拥有数千条访问记录。
最佳答案
是的,可以返回指定的结果集,但它并不漂亮。特别是,使用内联 View (MySQL 称之为“派生表”)意味着行将被写入临时 MyISAM 表,并且该操作对于大型集合来说可能会很昂贵,因此使用这种方法获得性能将可能需要在最里面的查询上进行一些谓词才能获得合理大小的数据集...例如
WHERE q.userID = 321
AND q.date_event >= '2012-01-01'
AND q.date_event < '2012-01-02'
注意:似乎“持续时间”的值应该受到限制...即,您是否希望周五下午 6 点的点击与周一上午 8 点的点击“匹配”,如果这被视为是时间的一部分“期间”。在下面的查询中,我将最大持续时间值指定为 6800 秒,这样 6800 就是可以返回的最大持续时间,任何大于此的持续时间都会“拆分”为两个持续时间。
以下是返回指定结果集的查询示例:
SELECT recordID
-- , s.userID
, s.first
, MAX(s.date_event) AS `last`
, MAX(TIMESTAMPDIFF(SECOND,s.first,s.date_event)) AS duration
-- , MAX(s.cnt) AS `cnt`
FROM (
SELECT IF(r.recordID = @record_id AND r.userID = @user_id AND r.date_event < (@date_event + INTERVAL 6800 SECOND),
@cnt := @cnt + 1, @cnt := 1) AS `cnt`
, IF(r.recordID = @record_id AND r.userID = @user_id AND r.date_event < (@date_event + INTERVAL 6800 SECOND),
@first, @first := r.date_event) + INTERVAL 0 SECOND AS `first`
, @record_id := r.recordID AS recordID
, @user_id := r.userID AS userID
, @date_event := r.date_event AS date_event
FROM ( SELECT @record_id := NULL, @user_id := NULL, @date_event := NULL, @cnt := 0, @first := NULL) i
JOIN ( SELECT q.recordID, q.userID, q.date_event
FROM record_log q
ORDER BY q.userID, q.date_event, q.recordID
) r
) s
GROUP
BY s.first
, s.userID
, s.recordID
ORDER
BY s.first
, s.userID
, s.recordID
注意:此查询假设一条记录上的“持续时间”将被另一条记录上的“持续时间”“分解”。 (如果用户点击一条记录,然后点击另一条记录,然后返回原始记录进行更多点击,则对原始记录的点击将被计为两个单独的持续时间。
<小时/>示例数据:
INSERT INTO record_log (recordID, userID, date_event) VALUES
('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')
关于mysql - 获取连续记录查看的持续时间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17350080/