类型一

有一张用户签到表【t_user_attendence】,标记每天用户是否签到(说明:该表包含所有用户所有工作日的出勤记录) ,包含三个字段:
• 日期【fdate】
• 用户id【fuser_id】
• 用户当天是否签到【fis_sign_in:0否1是】

问题1:

请计算截至当前每个用户已经连续签到的天数(输出表仅包含当天签到所有用户,计算其连续签到天数)

输出表【t_user_consecutive_days】:
• 用户id【fuser_id】
• 用户连续签到天数【fconsecutive_days】
解答逻辑:1.最近的一次未签到的日期 2.今天的日期-最近一次未签到日期。

  1. select fuser_id, datediff('2020-12-11',max_fdate) as fconsecutive_days
  2. from t_user_attendence t1
  3. join (
  4. select fuser_id, max(fdate) as max_fdate
  5. from t_user_attendence
  6. where fis_sign_in = 0
  7. group by fuser_id
  8. ) as t2 #最近一次未签到日期
  9. on t1.fuser_id = t2.fuser_id
  10. where t1.fdate = '2020-12-11' and t1.fis_sign_in = 1 #今天签到的用户

问题2:

请计算每个用户历史以来最大的连续签到天数(输出表为用户签到表中所有出现过的用户,计算其历史最大连续签到天数)

输出表【t_user_max_days】:
• 用户id【fuser_id】
• 用户最大连续签到天数【fmax_days】

1.计算每次的连续签到次数(1.所有未签到的天数 2.lag未签到日期 3. 日期相减-1)
2.排序 最大值

  1. select fuser_id, ifnull(datediff(fdate,pdate),0) as consective_days
  2. from (
  3. select fuser_id, fdate, lag(fdate) over (partition by fuser_id ordre by fdate) as pdate
  4. from (
  5. select fuser_id, fdate
  6. from t_user_attendence
  7. where fis_sign_in = 0
  8. ) as no_sign_in_date
  9. ) as lag_date
  10. group by fuser_id
  11. having consective_days = max(consective_days)
  12. order by consective_days desc;

类型二

练习1 计算连续登陆天数 关键词 row_number

百度数据部门的面试题,主要考察row_number
题目:SQL语句如何查询各个用户最长的连续登陆天数?如图左边是源表User,右边是需要达到的查询结果。

image.png

作者:李明轩Matthew
链接:https://www.jianshu.com/p/77597eadd3cc
思路1:登陆日期是连续值,通过datediff(curdate(),loadtime)-row_number()over(partition by uid order by loadtime desc)

判断连续的核心是row_number
因为row_number是连续的
所以day-row_number,如果值是恒定的,说明也是连续的,反之一定会变化

  1. select uid,max(active_days)
  2. from (
  3. select uid,cnt,count(*) as active_days
  4. from (
  5. select uid,
  6. datediff(curdate(),loadtime)-row_number()over(partition by uid order by loadtime desc) as cnt
  7. from users
  8. ) as t1
  9. group by uid,cnt
  10. ) as t2
  11. group by uid