mysql - 从时间戳中选择最后连续的天数(今天除外)

标签 mysql timestamp

我有一个表A_DailyLogins,其中包含列ID(自动递增)、Key(用户标识)和Date(时间戳)。我想要一个查询,它会根据 Key 从那些时间戳中返回最后连续天数,例如,如果他有昨天的一行,两天前的一行和三天前的另一行, 但最后一个不是四天前的,它会返回 3,因为这是用户最后登录的天数。

我的尝试是创建一个查询,选择按 Date DESC 排序的球员的最后 7 行(这是我最初想要的,但后来我认为这会很棒有所有最后连续的天数),然后我检索查询结果并比较日期(使用该语言[Pawn]的函数转换为年/月/日)并增加一个日期在另一个日期之前的连续天数一天一次。 (但与我认为只能用 MySQL 直接完成的相比,这是非常慢的)

我找到的最接近的是:Check for x consecutive days - given timestamps in database .但这仍然不是我想要的样子,它仍然很不一样。我尝试修改它,但这对我来说太难了,我在 MySQL 方面没有那么多经验。

最佳答案

上下文

consecutive login period 是用户在所有天都登录的时间段(在期间的每一天在 A_DailyLogins 中都有一个条目)在 A_DailyLogins 之前或之后没有条目同一用户的连续登录时间

number of consecutive daysconsecutive login period

中最大和最小日期之间的差值

consecutive login period 的最大日期之后(连续)没有登录条目..

连续登录期的最短日期之前(顺序)没有登录条目..

计划

  • left join A_DailyLogins to itself using same user and sequential dates where right is null to find maximums
  • analogous logic to find minimums
  • calculate row ordering over minimums and maximums with appropriate order by
  • join maximums and minimums on row number
  • filter where maximum login is yesterday/today
  • calculate date_diff between maximum and minimum in range
  • left join users to above resultset and coalesce over the case where user does not have a consecutive login period ending yesterday/today

输入

+----+------+------------+
| ID | Key  | Date       |
+----+------+------------+
| 25 | eric | 2015-12-23 |
| 26 | eric | 2015-12-25 |
| 27 | eric | 2015-12-26 |
| 28 | eric | 2015-12-27 |
| 29 | eric | 2016-01-01 |
| 30 | eric | 2016-01-02 |
| 31 | eric | 2016-01-03 |
| 32 | nusa | 2015-12-27 |
| 33 | nusa | 2015-12-29 |
+----+------+------------+

查询

select all_users.`Key`, 
coalesce(nconsecutive, 0) as nconsecutive
from
(
  select distinct `Key`
  from A_DailyLogins
) all_users
left join
(
  select
  lower_login_bounds.`Key`,
  lower_login_bounds.`Date` as from_login,
  upper_login_bounds.`Date` as to_login,
  1 + datediff(least(upper_login_bounds.`Date`, date_sub(current_date, interval 1 day))
                     , lower_login_bounds.`Date`) as nconsecutive
  from
  (
    select curr_login.`Key`, curr_login.`Date`, @rn1 := @rn1 + 1 as row_number
    from A_DailyLogins curr_login
    left join A_DailyLogins prev_login
    on curr_login.`Key` = prev_login.`Key`
    and prev_login.`Date` = date_add(curr_login.`Date`, interval -1 day)
    cross join ( select @rn1 := 0 ) params
    where prev_login.`Date` is null
    order by curr_login.`Key`, curr_login.`Date`
  ) lower_login_bounds
  inner join
  (
    select curr_login.`Key`, curr_login.`Date`, @rn2 := @rn2 + 1 as row_number
    from A_DailyLogins curr_login
    left join A_DailyLogins next_login
    on curr_login.`Key` = next_login.`Key`
    and next_login.`Date` = date_add(curr_login.`Date`, interval 1 day)
    cross join ( select @rn2 := 0 ) params
    where next_login.`Date` is null
    order by curr_login.`Key`, curr_login.`Date`
  ) upper_login_bounds
  on lower_login_bounds.row_number = upper_login_bounds.row_number
  where upper_login_bounds.`Date` >= date_sub(current_date, interval 1 day)
  and   lower_login_bounds.`Date` < current_date
) last_consecutive
on all_users.`Key` = last_consecutive.`Key`
;

输出

+------+------------------+
| Key  | last_consecutive |
+------+------------------+
| eric |                2 |
| nusa |                0 |
+------+------------------+

有效于 2016-01-03 运行

sqlfiddle

关于mysql - 从时间戳中选择最后连续的天数(今天除外),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31755051/

相关文章:

php - 需要帮助重构查询/数据库设计

php - 将第二个重复项发布到表中

php - 在浏览器上显示 mysql 存储的时间戳值

mysql - 使用mySQL从多个表中选择具有最新时间戳的数据

mysql - MySQL 主从复制的 HAProxy

mysql - 在 Rails 中计算日期范围内每天记录数的有效方法,无需每天进行一次查询

java日期格式化程序不会将正常小时格式更改为24小时格式

cassandra - 如何在 Cassandra 中将 Unix 10 位纪元时间存储和查询为人类可读的内容?

php高效读取文件并插入sql

php - Zend 框架 : MySQL insertion error of timestamp