hive/spark-sql经典笔试面试题(二)连续登录天数最大

问题描述

在数据仓库中存在这样一张表,记录了2019年所有用户在哪天登录了我司的网站或者app。数据如下:
表名:test2
字段:id string,pday string
hive/spark-sql经典笔试面试题(二)连续登录天数最大_第1张图片
需求:统计用户在本年中连续登录天数最大是几天?如:
用户A在7月1、2、3、4日连续登录了4天;6、7、8日连续3天;11、12连续2天。用户A的当年最大连续登录天数是4天
用户B在6月29日,6月30日,7月1日连续登录3天。用户B的当年最大连续登录天数是3天
需要的到的结果是这样的:
在这里插入图片描述

题目刨析

此题需要将连续的天数打上相同的标签进行聚合。得到连续天数数量之后,取到最大值。
可难点就是确定哪些天数是连续的,凭什么将连续的日期放在一起呢?
我的思路是这样的,我们需要两个辅助列。
第一列:将每个用户的登录日期从小到大排序
第二列:登录日期在当年是第几天
我们先将两个辅助列写出来,看看是什么效果:

select 
    id,
    pday,
    row_number() over(partition by id order by pday) as rn,
    dayofyear(from_unixtime(unix_timestamp(pday,'yyyyMMdd'),'yyyy-MM-dd')) as day_of_year
from 
    test2
order by id,rn;

hive/spark-sql经典笔试面试题(二)连续登录天数最大_第2张图片
细心的同学可能已经发现了,若将两个辅助列做差,连续登录和非连续登录的天数就展现出区别了。如:
对于A用户来说
182-1=181
183-2=181
184-3=181
185-4=181
187-5=182
188-6=182
189-7=182
192-8=184
193-9=184
差值都是181的就是连续登录了4天,差值为182的为连续登录3天
为什么中间会断开呢。就是因为在20190705这一天用户没有登录,所以连续登录断掉了
接下来的事就容易多了。

解答

有了之前的刨析,直接看到这个答案应该就很容易接受了。语言苍白无力,还是直接看代码吧。

select 
    id,
    max(continuation_days) as max_continuation_days
from
    (select 
        id,
        count(*) as continuation_days
    from
        (select 
            id,
            dayofyear(from_unixtime(unix_timestamp(pday,'yyyyMMdd'),'yyyy-MM-dd'))
                -row_number() over(partition by id order by pday) as sub
        from 
            test2
        )t0
    group by id,sub
    )t0
group by id

结语

  • 此题是我在面试的时候亲身经历过的面试题,在面试的时候面试官递给我一张纸,说完需求之后就留下我冥思苦想,见我一直皱着眉头也不下笔就对我进行了提醒,最后磕磕绊绊才写出来自己的答案。当时最困扰我的就是如何将连续的日期放在一起进行分组。
  • 题目短小精悍(表只有两列),不像其他题一样需要众多表连接,可真正实现起来却涉及到不少的知识点。如:字符串转时间戳,时间戳转时间日期,以及窗口函数,子查询,以及sql最基本的分组、聚合等。这些都是考点。
  • 稍微进行下拓展,如果计算的不是当年的连续登录日期,而是所有的日期。如2018年12月31日和2019年1月1日也视为连续登录。那答案中的dayofyear函数就不灵了,可以使用datediff函数,输入两个日期返回两个日期之间的天数。
    如:select date_diff(‘2019-12-13’,‘1970-01-01’) 返回 18243

你可能感兴趣的:(spark)