hive/spark-sql經典筆試面試題(二)連續登錄天數最大

問題描述

在數據倉庫中存在這樣一張表,記錄了2019年所有用戶在哪天登錄了我司的網站或者app。數據如下:
表名:test2
字段:id string,pday string
在這裏插入圖片描述
需求:統計用戶在本年中連續登錄天數最大是幾天?如:
用戶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;

在這裏插入圖片描述
細心的同學可能已經發現了,若將兩個輔助列做差,連續登錄和非連續登錄的天數就展現出區別了。如:
對於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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章