【问题标题】:Count rows after specific one在特定行之后计算行
【发布时间】:2015-05-05 07:24:13
【问题描述】:

一个表users 有三列:id, name, pass

另一个表logins 有一个user_id 列,一个isright boolean (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)似乎更难。我用谷歌搜索并发现了许多类似的问题,但没有一个是在询问在特定条件为真后如何计算行数。 (这更复杂 - 计算那个用户的登录,而不是每个人)

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

SQL 处理表格和一些数据:http://sqlfiddle.com/#!9/a932b

有什么想法吗?

【问题讨论】:

  • 您是否尝试过使用子查询获取上次成功登录的日期/时间,然后只计算日期/时间之后的日期/时间?如果您能给我描述一下您的两张桌子,我可能会提供更多帮助
  • 考虑提供适当的 DDL(和/或 sqlfiddle)以及所需的结果。
  • @JeremyC。 - 这是一个带有一些示例数据的 sqlfiddle:sqlfiddle.com/#!9/a932b

标签: mysql sql subquery left-join


【解决方案1】:

直接的方法是有两个派生表:一个获取每个用户的最后一次登录日期,另一个获取每个用户的最后一次成功登录日期。然后从用户中选择,外连接两个派生表,查看上次登录是否成功,统计上次成功登录后的(失败)登录次数。 (对于另一个 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 为 null,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 为上次成功登录后的失败次数。

这是一个小提琴:http://sqlfiddle.com/#!9/57b7d/1

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

  (
    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

【讨论】:

  • 这个答案绝对值得更多的支持!非常感谢!
  • 我对这种sql语法不是很熟悉,能不能给我一个提示,即使用户从来没有正确登录过,如何计算错误登录? (第 2 点)
  • 我已经相应地编辑了我的答案。请注意,我将 where last_successful_login.user_id = students.id 替换为 where user_id = students.id,因为 last_successful_login.user_id 在外部连接情况下将为空。
【解决方案2】:

我猜你可以做类似的事情

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)

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

【讨论】:

    【解决方案3】:

    如何使用仅包含最新登录详细信息的视图和以下查询

    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)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-18
      相关资源
      最近更新 更多