题解 | #最大连续回答天数大于等于3天的用户及其对应等级#
某乎问答最大连续回答问题天数大于等于3天的用户及其对应等级
https://www.nowcoder.com/practice/e080f8a685bc4af3b47749ca3310f1fd
题目:
统计最大连续回答问题的天数大于等于3天的用户及其等级。若有多条符合条件的数据,按author_id升序排序
难点:
- 本题目最大的难点就在于:如何判断几个日期是否连续的 —— 当一组日期按照升序排序时,如果某几个日期是连续的,它们减去本身的DENSE RANK,会发现都是相减的结果都是同一天
(不得不说,不知道是哪位先发现这个切入角度的的,真的是个人才。要是哪位知道这种数学规律的出处,求分享!)
- 另外,我发现大多数回答忽略了一个特殊情况(虽然题目实例中并没有考虑到):若一个用户有10次连续登录超过三天的情况,则该用户会得出10组“同一天”日期及其对应的连续天数(10个大于等于3的随机整数) —— 针对这一特殊情况,可在最终的答案中再嵌套一层MAX查询
解题步骤
步骤 1:找出每个用户的答题日期及日期的升序排名
- 注意,因为用户可在同一天答题多次,因此需要使用DISTINCT进行去重
SELECT DISTINCT a1.author_id, a2.author_level, answer_date, DENSE_RANK() OVER (PARTITION BY a1.author_id ORDER BY answer_date ASC) AS ranking FROM answer_tb AS a1 LEFT OUTER JOIN author_tb AS a2 ON a1.author_id = a2.author_id
步骤 2:根据“答题日期 - 排序”所得出的日期进行聚合,计算相减日期为同一天的对应行数,即为连续答题天数
- 最主要的是要知道:DATE_SUB()得出的结果日期,也是聚合字段之一,要根据该结果计算对应的行数
- 随后,再把连续答题天数大于等于3的筛选出来即可
SELECT author_id, author_level, COUNT(author_id) AS days_cnt FROM (SELECT DISTINCT a1.author_id, a2.author_level, answer_date, DENSE_RANK() OVER (PARTITION BY a1.author_id ORDER BY answer_date ASC) AS ranking FROM answer_tb AS a1 LEFT OUTER JOIN author_tb AS a2 ON a1.author_id = a2.author_id) AS t1 GROUP BY author_id, author_level, DATE_SUB(answer_date, INTERVAL ranking DAY) HAVING days_cnt >= 3 ORDER BY author_id ASC;
步骤 3:若是同一用户有多次连续答题超过3次的情况,则仍需嵌套一层MAX函数查询,找出每个用户的最大连续天数即可
- 其实步骤2的解法已经能通过本次题目了,但考虑到仍有一个特殊情况,再完善一下查询语句
SELECT author_id, author_level, MAX(days_cnt) AS days_cnt FROM (SELECT author_id, author_level, COUNT(author_id) AS days_cnt FROM (SELECT DISTINCT a1.author_id, a2.author_level, answer_date, DENSE_RANK() OVER (PARTITION BY a1.author_id ORDER BY answer_date ASC) AS ranking FROM answer_tb AS a1 LEFT OUTER JOIN author_tb AS a2 ON a1.author_id = a2.author_id) AS t1 GROUP BY author_id, author_level, DATE_SUB(answer_date, INTERVAL ranking DAY) HAVING days_cnt >= 3) AS t2 GROUP BY author_id, author_level ORDER BY author_id ASC;