我需要计算用户在过去一小时内是否连续三次失败登录尝试。
例如
id userid status logindate
1 1 0 2014-08-28 10:00:00
2 1 1 2014-08-28 10:10:35
3 1 0 2014-08-28 10:30:00
4 1 0 2014-08-28 10:40:00
在上面的示例中,状态0表示尝试失败,1表示成功尝试。
我需要一个查询,它将计算在过去一小时内发生状态为0的用户的三个连续记录。
我在下面尝试了查询
SELECT COUNT( * ) AS total, Temp.status
FROM (
SELECT a.status, MAX( a.id ) AS idlimit
FROM loginAttempts a
GROUP BY a.status
ORDER BY MAX( a.id ) DESC
) AS Temp
JOIN loginAttempts t ON Temp.idlimit < t.id
HAVING total >1
结果:
total status
2 1
我不知道为什么它显示为 1 的状态。我还需要在logindate和status字段中添加where条件,但不知道它是如何工作的
答案 0 :(得分:2)
对于连续计数,您可以使用用户定义的变量来记录系列值,如下面的查询我使用@g
和@r
变量,在内部查询中我存储的当前状态值可以是1/0,如果表达式我将@g
中存储的值与状态列进行比较,如果它们都相等,则@g
保持前一行值,前一行的状态等于当前行的状态然后不要更改存储在@r
中的值,如果这些值与@g <> a.status
不匹配,那么将@r
增加为1,有一点需要注意我正在使用带有id列的顺序并假设它设置为auto_increment,因此对于连续的1 @r
值将与@r
相同,第一个状态1为3,再次状态为1,因此@r
将为3,直到状态发生变化状态0反之亦然0反之亦然
SELECT t.userid,t.consecutive,t.status,COUNT(1) consecutive_count
FROM (
SELECT a.* ,
@r:= CASE WHEN @g = a.status THEN @r ELSE @r + 1 END consecutive,
@g:= a.status g
FROM attempts a
CROSS JOIN (SELECT @g:=2, @r:=0) t1
WHERE a.`logindate` BETWEEN '2014-08-28 10:00:00' AND '2014-08-28 11:00:00'
ORDER BY id
) t
GROUP BY t.userid,t.consecutive,t.status
HAVING consecutive_count >= 3 AND t.status = 0
现在在父查询中,我按userid
对结果进行分组,案例表达式的结果值我有名称是consecutive
和status
来获取每个用户的连续状态的计数< / p>
有一点要注意上面的查询,它必须提供 像我之间使用的小时范围没有这个将会更多 很难在一小时内准确找到3个连续状态
INSERT INTO attempts
(`id`, `userid`, `status`, `logindate`)
VALUES
(1, 1, 0, '2014-08-28 10:00:00'),
(2, 1, 1, '2014-08-28 10:10:35'),
(3, 1, 0, '2014-08-28 10:30:00'),
(4, 1, 0, '2014-08-28 10:40:00'),
(5, 1, 0, '2014-08-28 10:50:00'),
(6, 2, 0, '2014-08-28 10:00:00'),
(7, 2, 0, '2014-08-28 10:10:35'),
(8, 2, 0, '2014-08-28 10:30:00'),
(9, 2, 1, '2014-08-28 10:40:00'),
(10, 2, 1, '2014-08-28 10:50:00')
;
从id 3到5你可以看到你可以看到用户ID 1的连续0,同样id 6到8用户ID 2连续0并且他们在一个小时范围内使用上面的查询你可以得到如下结果
userid consecutive status consecutive_count
------ ----------- ------ -------------------
1 2 0 3
2 2 0 3
Fiddle Demo
答案 1 :(得分:0)
M Khalid Junaid的答案很棒,但当我点击它时,他的小提琴演示并不适合我。
这是Fiddle Demo,在撰写本文时起作用。
如果以后它没有工作,我在架构中使用了以下内容:
CREATE TABLE attempts
(`id` int, `userid` int, `status` int, `logindate` datetime);
INSERT INTO attempts
(`id`, `userid`, `status`, `logindate`)
VALUES
(1, 1, 0, '2014-08-28 10:00:00'),
(2, 1, 1, '2014-08-28 10:10:35'),
(3, 1, 0, '2014-08-28 10:30:00'),
(4, 1, 0, '2014-08-28 10:40:00'),
(5, 1, 0, '2014-08-28 10:50:00'),
(6, 2, 0, '2014-08-28 10:00:00'),
(7, 2, 0, '2014-08-28 10:10:35'),
(8, 2, 0, '2014-08-28 10:30:00'),
(9, 2, 1, '2014-08-28 10:40:00'),
(10, 2, 1, '2014-08-28 10:50:00')
;
这是查询:
SELECT t.userid,t.consecutive,t.status,COUNT(1) consecutive_count
FROM (
SELECT a.* ,
@r:= CASE WHEN @g = a.status THEN @r ELSE @r + 1 END consecutive,
@g:= a.status g
FROM attempts a
CROSS JOIN (SELECT @g:=2, @r:=0) t1
WHERE a.`logindate` BETWEEN '2014-08-28 10:00:00' AND '2014-08-28 11:00:00'
ORDER BY id
) t
GROUP BY t.userid,t.consecutive,t.status
HAVING consecutive_count >= 3 AND t.status = 0;