基本上,我正在尝试的结果是:“获取过去一定时间内有 0个不成功记录的成功记录数”。“成功”和“不成功”只是指列的值。
虽然它有点复杂,但这里是我正在处理的表的描述:
`log`
id int PRIMARY KEY AUTO_INCREMENT
fingerprint_id int (foreign key)
status boolean
date timestamp
我们拥有的小系统的工作流程是,当用户刷他们的指纹时,会在此表中添加一条记录,并status
根据它是否匹配来设置记录(同样,还有更多内容,我只是想简化一下)。我们fingerprint_id
基于用户执行此操作得到 ,因此这是将记录与人员相关联的标识符。
目前,我们要求他们最多尝试 3 次。因此,他们可以在 3 之 1、3 之 2、3 之 3 或根本不匹配。这意味着他们的“组”中可以有 1、2 或 3 条记录。虽然这不是真的,但我们可以假设用户将继续尝试,直到匹配或达到 3 次失败尝试(我们发现有时人们可能会在失败一两次后不再继续)。
以下是一些数据的示例:
id fp_id status date
----------------------------------------
20 2 0 '2013-01-21 12:30:01'
21 2 0 '2013-01-21 12:30:05'
22 2 0 '2013-01-21 12:30:10'
23 9 1 '2013-01-21 12:31:30'
24 1 0 '2013-01-21 12:35:00'
25 1 1 '2013-01-21 12:35:05'
数据中,用户 ( fingerprint_id
) 2 尝试了 3 次,从未匹配。用户 9 第一次尝试匹配。用户 1 尝试一次失败,然后再次尝试并匹配。
重点是找出35秒前有多少成功(status
=1)的日志记录有0个不成功( =0)的记录。status
当然,“连接”它们的唯一方法是通过fingerprint_id
.
同样,我们假设了很多事情,但这很好。
这是我的尝试:
SELECT COUNT(*)
FROM log AS log_main
WHERE log_main.status=1 AND
(SELECT COUNT(*)
FROM log AS log_inner
WHERE log_inner.fingerprint_id=log_main.fingerprint_id AND
log_inner.status=0 AND
log_inner.date<log_main.date AND log_inner.date>=(log_main.date - INTERVAL 35 SECOND))=0
^ 我希望这个选择所有成功的记录,这些记录在 35 秒前(对于该用户)内发生的不成功记录计数为 0。但我不知道,因为查询需要 600 多秒。我刚刚发现了如何延长 MySQL Workbench 的最大超时时间,但无论哪种方式,都需要很长时间。该表总共有大约 120,000 条记录,所以我不确定这是否足以使这个查询变得如此缓慢。
无论如何,这是另一个尝试:
SELECT COUNT(*)
FROM (SELECT log.fingerprint_id, log.date
FROM log
WHERE log.status=1) successful,
(SELECT log.fingerprint_id, log.date
FROM log
WHERE log.status=0) unsuccessful
WHERE successful.fingerprint_id=unsuccessful.fingerprint_id AND
unsuccessful.date<successful.date AND unsuccessful.date>=(successful.date - INTERVAL 35 SECOND)
^ 我觉得这个更接近,但当然,没有关于过去匹配多少条记录的“计数”的比较。这就是我对如何解决感到困惑的部分。我有一种感觉,它与使用GROUP BY
或代替使用有关IN
,但我所做的似乎不起作用(从某种意义上说,它超过了 600 秒或类似的时间)。这是我尝试过的一个例子GROUP BY
SELECT successful.id, COUNT(*) cnt
FROM (SELECT log.fingerprint_id, log.date, log.id
FROM log
WHERE log.status=1) successful,
(SELECT log.fingerprint_id, log.date, log.id
FROM log
WHERE log.status=0) unsuccessful
WHERE successful.fingerprint_id=unsuccessful.fingerprint_id AND
unsuccessful.date<successful.date AND unsuccessful.date>=(successful.date - INTERVAL 35 SECOND)
GROUP BY successful.id
^ 但结果仅包含计数不为 0 的行。我猜这是因为该WHERE
条款。但我只需要 0 计数。
我尝试了很多组合,我认为我的大脑只是油炸了。