【问题标题】:MySQL count a number of entries within time period sharing at least 1 of 3 columnsMySQL 计算时间段内至少共享 3 列中的 1 列的条目数
【发布时间】:2014-09-22 01:37:06
【问题描述】:

我有一个记录无效用户登录尝试的表。每次进行无效尝试时,用户名、用户 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.1.1与显示的所有ID一致,您可以根据IP地址的前3组数字。这似乎是与您发布的所有内容的唯一密切关系。
  • 谢谢。 IP 只是一个例子,实际上它们将是真实的并且变化很大。这些用户仍然以某种方式联系在一起,因为每个人都彼此共享 ID、IP 或电子邮件。甚至 id2 和 id5 也是相关的,因为虽然它们不共享直接字段,但它们通过 id4 等具有二阶关系。
  • 啊,我明白了。是的,我可以看到戈登的回答如何解释了试图解决问题的复杂性。这是一个令人头疼的问题。

标签: php mysql sql email


【解决方案1】:

您所拥有的是记录之间的连接图,其中边缘是电子邮件、用户名和 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);

然后您必须重复此操作,直到没有更新为止。

【讨论】:

  • 谢谢,这是有道理的。你对 PHP 中的这种算法有什么建议吗?我在想一些关于数组的东西,但我无法理解它。
猜你喜欢
  • 1970-01-01
  • 2023-02-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-04
  • 1970-01-01
  • 1970-01-01
  • 2017-06-06
相关资源
最近更新 更多