MYSQL计算行直到最后一行不同

时间:2016-02-27 13:56:07

标签: mysql sql

我有一个表格中的事件表:

|  User  |     Event         |   Date  |
| User A | Failed Log In     |   ...   | 
| User A | Failed Log In     |   ...   |
| User B | Failed Log In     |         |
| User A | Successful Log In |         |
| User B | Successful Log In |         |

我想要做的是计算所有失败的登录信息'对于每个用户最后一次成功登录'所以我可以在表单中创建一个视图:

|  User  | Failed Log in attempts |
| User A |            2           |
| User B |            1           |

这可以在SQL中做到吗?或者我是否需要将此逻辑拉入我的应用程序?

2 个答案:

答案 0 :(得分:2)

SQL表表示无序集,因此除非列指定排序,否则不存在“last”或“before”。因此,这个答案假定某些eventdatetime列包含该信息,尽管自动递增id也可以正常工作(并且可能更好)。

我认为这可以满足您的需求:

select e.user, count(*) as NumFailedAttempts
from events e
where e.event = 'Failed Log In' and
      e.eventdatetime > (select max(e2.eventdatetime)
                         from events e2
                         where e2.user = e.user and e2.event = 'Successful Log In'
                        );

如果您想要包含零(没有登录失败的那些),那么您可以将其加入到users表中。

答案 1 :(得分:1)

@GordonLinoff回答(这是正确的)的替代方法,可以是将表连接到自身,以获得最后的登录时间,而不是使用子查询:

SELECT events.user, COUNT(events.event) AS FailedCount
FROM events
LEFT JOIN (
  SELECT MAX(`date`) AS lastlogin
  FROM events
  WHERE event = 'Success'
) AS last ON (events.user = last.user)
WHERE
  event = 'Failed'
  AND
  `date` > last.lastlogin
GROUP BY user, event

http://sqlfiddle.com/#!9/96faa/1/0

这是做什么的:

  • events表加入自身,从而为每一行添加一个临时lastLogin字段;
  • 选择上次登录后发生的失败事件;
  • 对已失败事件的已过滤列表进行分组,以便对其进行计数。

MySQL documentation: Using More Than one Table和本文中提供了将表格加入自身的简短介绍:Joining a Table to Itself

与子查询变体相比,这可以带来最小的性能优势。实际上它是主观的,取决于DBMS的特定版本和"心情"查询优化器。

关于连接与子查询的性能的讨论可以在这里找到: