douwen8424 2014-09-22 01:37
浏览 93

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

I have a table that logs invalid user login attempts. Every time an invalid attempt is made, the username, user IP, user email and time/date is stored in the database.

What I'd like to do is check if within ANY 24 hour time period there has been more than X invalid attempts by the same user. However, the users can change the email, username or IP at any point. So, I need to check that anyone of these 3 fields is in common.

For example:

  • User ID: 1; IP: 1.1.1.1; Email: test@test.com
  • User ID: 2; IP: 1.1.1.1; Email: test2@test.com
  • User ID: 1; IP: 1.1.1.2; Email: test3@test.com
  • User ID: 4; IP: 1.1.1.4; Email: test@test.com
  • User ID: 5; IP: 1.1.1.4; Email: test5@test.com

All of these would match as the SAME user because they share EITHER the user ID, the IP or the email. Then I need to output all user IDs, IPs and emails so I can ban any user in another table that matches these criteria.

  • 写回答

1条回答 默认 最新

  • dphs48626 2014-09-22 01:42
    关注

    This is too long for a comment.

    What you have is a graph of connections between records, where the edges are email, username, and IP. You need to traverse this graph to find connected subgraphs. This is difficult. In your example, for instance, id2 and id2 are connected, but they have no fields in common.

    So, you need a graph walking algorithm. MySQL does not have constructs that support such algorithms directly in SQL. You can write a stored procedure to find such groups, but this is not something you can do with a single SQL statement

    EDIT:

    When I've encountered this problem before, I have used SQL, with repeated update statements. The idea is to assign to each record the lowest userid encountered.

    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);
    

    You then have to repeat this until nothing gets updated.

    评论

报告相同问题?

悬赏问题

  • ¥20 腾讯企业邮箱邮件可以恢复么
  • ¥15 有人知道怎么将自己的迁移策略布到edgecloudsim上使用吗?
  • ¥15 错误 LNK2001 无法解析的外部符号
  • ¥50 安装pyaudiokits失败
  • ¥15 计组这些题应该咋做呀
  • ¥60 更换迈创SOL6M4AE卡的时候,驱动要重新装才能使用,怎么解决?
  • ¥15 让node服务器有自动加载文件的功能
  • ¥15 jmeter脚本回放有的是对的有的是错的
  • ¥15 r语言蛋白组学相关问题
  • ¥15 Python时间序列如何拟合疏系数模型