我有一个表格中的事件表:
| 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中做到吗?或者我是否需要将此逻辑拉入我的应用程序?
答案 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的特定版本和"心情"查询优化器。
关于连接与子查询的性能的讨论可以在这里找到: