MySQL计算时间段内的多个条目,共享3列中的至少1列

时间:2014-09-22 01:37:07

标签: php mysql sql email

我有一个记录无效用户登录尝试的表。每次进行无效尝试时,用户名,用户IP,用户电子邮件和时间/日期都将存储在数据库中。

我想做的是检查在任何24小时的时间段内,同一用户是否有超过X次无效尝试。但是,用户可以随时更改电子邮件,用户名或IP。所以,我需要检查这3个字段中的任何一个是否共同。

例如:

  • 用户ID:1; IP:1.1.1.1;电子邮件:test@test.com
  • 用户ID:2; IP:1.1.1.1;电子邮件:test2@test.com
  • 用户ID:1; IP:1.1.1.2;电子邮件:test3@test.com
  • 用户ID:4; IP:1.1.1.4;电子邮件:test@test.com
  • 用户ID:5; IP:1.1.1.4;电子邮件:test5@test.com

所有这些都将作为SAME用户匹配,因为他们共享用户ID,IP或电子邮件。然后我需要输出所有用户ID,IP和电子邮件,以便我可以禁止另一个符合这些条件的表中的任何用户。

1 个答案:

答案 0 :(得分:3)

评论太长了。

您所拥有的是记录之间的连接图,其中边缘是电子邮件,用户名和IP。您需要遍历此图以查找连接的子图。这是困难的。例如,在您的示例中,id2和id2已连接,但它们没有共同的字段。

所以,你需要一个图形行走算法。 MySQL没有直接在SQL中支持这种算法的结构。您可以编写存储过程来查找此类组,但这不是您可以使用单个SQL语句执行的操作

编辑:

当我以前遇到过这个问题时,我使用了SQL,重复update个语句。我们的想法是为每条记录分配遇到的最低用户ID。

create table tgroup as
    select t.*, id as grpid
    from table t;

update tgroup join
       (select email, min(id) as minid
        from tgroup t
        group by email
       ) tt
       on tt.email = tgroup.email and
          tt.minid < tgroup.id
    set tgroup.id = least(tt.minid, tgroup.id);

update tgroup join
       (select ip, min(id) as minid
        from tgroup t
        group by ip
       ) tt
       on tt.ip = tgroup.ip and
          tt.minid < tgroup.id
    set tgroup.id = least(tt.minid, tgroup.id);

然后你必须重复这个,直到没有任何更新。