我有一个mysql表,由一个破损的应用程序提供服务,有几百万行,有无意义的登录/注销。此应用程序目前无法修复,因此我尝试编写一个查询,以区分任何和所有时间戳(在未显示的日期范围内)之间的时间(以秒为单位),该时间戳匹配“agentlogin”之前的“agentlogout”行,同时忽略不符合该条件的所有其他行。
我一直在这个网站上搜索了好几个小时,虽然我找到了一些很好的查询示例,但它们只能处理表格(由编写良好的应用程序提供服务),这些表格具有登录,然后是注销,而不是这些重复的东西。
这是表格:
+---------+---------------------+-------+-------------+------------------+ | id | calldate | agent | etype | uniqueid | +---------+---------------------+-------+-------------+------------------+ | 1838073 | 2017-11-02 13:21:00 | 503 | agentlogoff | 1509628860.54414 | | 1838232 | 2017-11-02 14:46:19 | 503 | agentlogoff | 1509633979.54881 | | 1838323 | 2017-11-02 15:27:50 | 503 | agentlogoff | 1509636470.55125 | | 1838373 | 2017-11-02 15:51:04 | 503 | agentlogin | 1509637864.55274 | | 1838385 | 2017-11-02 15:55:57 | 503 | agentlogoff | 1509638157.55318 | | 1838460 | 2017-11-02 16:28:52 | 503 | agentlogin | 1509640132.55533 | | 1838472 | 2017-11-02 16:35:23 | 503 | agentlogoff | 1509640523.55564 | | 1838499 | 2017-11-02 16:42:35 | 503 | agentlogin | 1509640954.55630 | | 1838567 | 2017-11-02 17:16:02 | 503 | agentlogoff | 1509642962.55820 | | 1838686 | 2017-11-02 18:04:17 | 503 | agentlogoff | 1509645857.56162 | | 1838861 | 2017-11-02 19:48:59 | 503 | agentlogoff | 1509652139.56778 | | 1838896 | 2017-11-02 20:11:37 | 503 | agentlogoff | 1509653497.56914 | +---------+---------------------+-------+-------------+------------------+
简而言之,我试图获得所有匹配对之间的总和秒数。我最接近的是
SELECT round(e2.uniqueid - e1.uniqueid) as seconds
FROM dumbtable e1
LEFT JOIN dumbtable e2
ON e1.agent = e2.agent AND e2.etype ='agentlogoff' AND e1.calldate < e2.calldate
LEFT JOIN dumbtable e3
ON e1.agent = e3.agent AND e1.calldate < e3.calldate AND e3.calldate < e2.calldate
WHERE e1.agent = '503' and e1.etype='agentlogin'
GROUP BY e1.agent;
...但这只是第一个匹配对的秒数而不是其他任何东西。
+---------+ | seconds | +---------+ | 293 | +---------+
非常感谢任何帮助
编辑:
见评论,(感谢沃尔特解决第一个问题!)我忘了展示一个能解决这两个问题的例子。除了仅通过登录解决登录对登录对之外,我还需要仅将登录的第一个实例与下一个登出实例进行比较,而不管其间的登录行。试图更清楚地描述,如果有
0退出 - &gt; 1次登录 - &gt; 2登录 - &gt; 3登录 - &gt; 4退出 - &gt; 5退出 - &gt; 6退出 - &gt;登录等
我希望在最后一次登出(4)时“配对”和timediff最早登录(1)并忽略2,3,5,6。我希望这是有道理的,这就是我应该如何制定我原来的问题。基本上,此表中唯一合法的时间戳是每次最早登录,然后是下一次最早的注销。
以下是多个登录行的示例。箭头是我在几秒钟内需要timediff的合法条目,其他一切都应该被忽略。
+---------+---------------------+-------+-------------+------------------+
| id | calldate | agent | etype | uniqueid |
+---------+---------------------+-------+-------------+------------------+
| 1838073 | 2017-11-02 13:21:00 | 503 | agentlogoff | 1509628860.54414 |x
| 1838232 | 2017-11-02 14:46:19 | 503 | agentlogoff | 1509633979.54881 |x
| 1838323 | 2017-11-02 15:27:50 | 503 | agentlogoff | 1509636470.55125 |x
| 1838373 | 2017-11-02 15:51:04 | 503 | agentlogin | 1509637864.55274 |<--in
| 1838374 | 2017-11-02 15:52:04 | 503 | agentlogin | 1509637866.55274 |x
| 1838375 | 2017-11-02 15:53:04 | 503 | agentlogin | 1509637867.55274 |x
| 1838385 | 2017-11-02 15:55:57 | 503 | agentlogoff | 1509638157.55318 |<--out
| 1838460 | 2017-11-02 16:28:52 | 503 | agentlogin | 1509640132.55533 |<--in
| 1838472 | 2017-11-02 16:35:23 | 503 | agentlogoff | 1509640523.55564 |<--out
| 1838499 | 2017-11-02 16:42:35 | 503 | agentlogin | 1509640954.55630 |<--in
| 1838567 | 2017-11-02 17:16:02 | 503 | agentlogoff | 1509642962.55820 |<--out
| 1838686 | 2017-11-02 18:04:17 | 503 | agentlogoff | 1509645857.56162 |x
| 1838861 | 2017-11-02 19:48:59 | 503 | agentlogoff | 1509652139.56778 |x
| 1838896 | 2017-11-02 20:11:37 | 503 | agentlogoff | 1509653497.56914 |x
+---------+---------------------+-------+-------------+------------------+
另外,我希望我不是通过提出问题,获得完美答案,然后改变问题来违反规则。遗憾!!!
答案 0 :(得分:0)
我最近几次遇到过这样的要求。这是我的评价:
如果您的id
字段有自动增加选项,则下面的语句可以帮助您:
SELECT round(uniqueid2 - uniqueid1) AS seconds
FROM
(
SELECT uniqueid AS uniqueid1,
(SELECT uniqueid FROM dumbtable WHERE agent = '503' AND etype = 'agentlogoff' AND id > t1.id ORDER BY id LIMIT 1) AS uniqueid2
FROM dumbtable AS t1 WHERE agent = '503' AND etype = 'agentlogin'
) AS t;
这里的关键点是:
agentlogin
记录重复执行此操作。id
列和limit 1
子语句找出准确的下一个匹配行(agentlogoff
此处)。此处的自动增量字段不是必需的,在这种情况下您也可以使用calldate
。对于第二个问题:
如果我是你,我会备份表,删除所有无效记录,然后运行我给你的第一个查询。它易于理解,易于实现,运行速度也更快。
删除无效记录:
DELETE
FROM dumbtable AS t1
WHERE etype = (SELECT etype FROM dumbtable WHERE id < t1.id ORDER BY id DESC LIMIT 1);
当然,我可以给你另一个查询来完成这项工作,但它会非常复杂,而且非常慢。