计算特定行后的行数

Count rows after specific one

A table users 有三列:id, name, pass.

另一个table loginsuser_id列,一个isright布尔值(tinyint)列,表示登录是否成功,还有一个date栏目。

我需要一个简单的left join来获取用户名和他的密码(1),最后一次登录日期时间(成功与否) (2)以及特定用户自上次成功登录后的登录次数(3).

(1) 和 (2) 我可以使用

实现
SELECT name, pass, MAX(date)
FROM users
LEFT JOIN logins ON logins.id = users.id
-- here either "GROUP BY users.id" or "WHERE users.id = 1234"

但是(3)好像比较难。我用谷歌搜索并发现了许多类似的问题,但其中 none 询问在特定条件为真后如何准确计算行数。 (甚至更复杂 - 计算 那个 用户的登录数,而不是每个人)

我什至不知道如何在单独的查询中执行此操作(我更喜欢对这 3 件事进行一个查询,而且我想我必须使用子查询,尽管我更喜欢联接)。

SQL fiddle 与 tables 和一些数据:http://sqlfiddle.com/#!9/a932b

有什么想法吗?

如何使用仅具有最新登录详细信息的视图与以下查询

select l.user_id, l.date, l.isright from logins l
where l.date >= (select max(l2.date) from logins l2
    where l2.isright=1 and l2.user_id = l.user_id)

直接的方法是有两个派生表:一个获取每个用户的最后登录日期,另一个获取每个用户的最后一个成功登录日期。然后select from users, outer join 两个派生表,看上次登录是否成功,统计上次登录成功后的(失败)次登录。 (对于另一个 DBMS,您宁愿使用 MySQL 缺少的分析功能。)

select 
  users.name, 
  users.pass, 
  (
    select max(isright)
    from logins 
    where user_id = students.id and date = last_login.date
  ) as last_login_successful,
  (
    select count(*)
    from logins
    where user_id = students.id and date > last_successful_login.date
  ) as last_logins_failed
from users
left outer join
(
  select user_id, max(date) as date
  from logins
  group by user_id
) last_login on last_login.user_id = users.id
left outer join
(
  select user_id, max(date) as date
  from logins
  where isright = 1
  group by user_id
) last_successful_login on last_successful_login.user_id = users.id;

这为每个用户提供了四种可能性:

  1. 用户从未尝试登录。 last_login_successful 为空,last_logins_failed 无意义。
  2. 用户登录全部失败。 last_login_successful为0,last_logins_failed无意义。
  3. 用户上次登录成功。 last_login_successful为1,last_logins_failed无意义。
  4. 用户登录成功一次,但至少上次登录失败。 last_login_successful为0,last_logins_failed为上次登录成功后的失败次数。

这里是 fiddle:http://sqlfiddle.com/#!9/57b7d/1

编辑:当用户从未登录时也计算失败的登录:如果用户从未登录,他们的 last_login.date 为空。在 last_logins_failed 中,您想计算上次登录发生在 beforenever:

的所有记录
  (
    select count(*)
    from logins
    where user_id = students.id and (date > last_successful_login.date
    or last_successful_login.date is null)
  ) as last_logins_failed

我猜你可以做类似

select count(*)
from logins as l join users as u on l.user_id = u.id
where l.timestamp > (select max(timestamp)
                     from logins
                     where user_id = u.id and isright = 1)

获取用户成功登录的最后时间戳(子查询) 然后获取时间戳大于用户时间戳的所有登录的计数,这会自动为您提供不成功的登录,因为您将最后一次成功的登录作为参考 timestamp/datetime