2012-01-05 36 views
3

由于我下面的表结构:查询,选择所有行自去年成功

enter image description here

我试图建立一个查询,将返回数失败的登录尝试每个IP 因为在过去一小时内最后一次成功登录该IP。例如,你会注意到在过去一个小时内,来自单个IP的多个失败尝试(0),但自上次成功登录(#145)以来,只有1次(#146),这就是我想要返回。

该查询也应该是动态的并返回分组IP的行。

到目前为止,这是我,但我认为@ipa正在恢复NULL

SELECT COUNT(*) tries, @ipa := login_ip 
FROM login_log 
WHERE login_id > (
    SELECT MAX(login_id) 
    FROM login_log 
    WHERE login_success = 1 
    AND login_ip = @ipa 
) 
AND login_success = 0 
AND login_date > NOW() - 3600 
GROUP BY login_ip 
ORDER BY tries DESC; 

感谢

+0

在使用前似乎没有设置“@ ipa”。 – 2012-01-05 20:14:54

回答

2

别名表,并尝试这种方式,为您的@ipa变量无所事事为您提供:

SELECT COUNT(1) tries, l.login_ip 
FROM login_log l 
WHERE login_id > (
    SELECT MAX(login_id) 
    FROM login_log l2 
    WHERE l2.login_success = 1 
    AND l2.login_ip = l.login_ip 
) 
AND login_success = 0 
AND login_date > NOW() - 3600 
GROUP BY login_ip 
ORDER BY tries DESC; 

此外,您可以用join做到这一点:

select 
    count(1) tries, 
    log1.login_ip 
from 
    login_log log1 
    inner join (
     select 
      login_ip, 
      max(login_date) as max_date 
     from 
      login_log 
     where 
      login_success = 1 
     group by 
      login_ip 
    ) log2 on 
     log1.login_ip = log2.login_ip 
where 
    log1.login_success = 0 
    and log1.login_date > NOW() - 3600 
    and log1.login_date > log2.max_date 
group by 
    login_ip 
order by tries desc 

你可以尝试两种方式,看看哪一种更快。

+0

在第二行的第8行末尾缺少一个逗号,但除此之外它的作用!而且速度更快,因为我不必做子查询。谢谢! – 2012-01-05 20:36:16

+0

@stevether - 啊,对于错过的逗号感到抱歉。修正:)并澄清,你正在做一个子查询,只是不相关的子查询。不同之处在于前者只运行一次,而后者每行运行*,这可能需要一点时间。 – Eric 2012-01-05 20:37:47

+0

如果从来没有成功登录过IP,我该如何才能使其工作?它只是不返回行,但它应该。 – 2012-01-05 20:50:55