Hive中抽取連續多天登錄用戶


昨天群上有人發個阿里的面試題,題目描述大概如下:

數據源:用戶登錄表,只有倆個字段,uid和dt

試用HQL抽取出連續登錄了K天的用戶uid

第一個想法就是直接用一個UDF解決,按uid分組,把dt收集起來然后在UDF里面判斷是否滿足條件

SELECT
    uid,
    isExist(collect_set(dt), k) flag
FROM
    table_name
GROUP BY
    uid
HAVING
    flag = 1;

其中isExist的邏輯是判斷collect_set中是否存在k個連續的值

這種方法簡單明了,但是需要額外的寫一個UDF,對於不懂JAVA的來說確實比較麻煩

 

今天群里有個神人給出了一種新的解決思路,十分完美的解決了,下面是具體代碼

SELECT 
    uid, MAX(dt) - MIN(dt) diff, COLLECT_set (dt) 
FROM
    (SELECT 
        a.uid, a.dt, dt - rn num 
    FROM
        (SELECT 
            uid, dt, row_number () over (PARTITION BY uid 
        ORDER BY dt) rn 
        FROM
            table_name
        GROUP BY uid, dt) a) a 
GROUP BY uid, num 

該思路首先利用窗口函數以uid分組然后按照dt排序給出每個dt在排序中的位置,然后用求出dt與位置的差(記為num)

最后按照uid和num做一個聚合,容易發現同一個num組內的dt是連續的值

然后直接計數(count(*))就可以得出結果了

上面的代碼只是為了更加方便看到輸出的結果正確性,輸出結果如下:

UID        DIFF    DT_ARRAY
1043736    3.020140815    20140814    20140813    201408121043736    0.0201408181043736    1.020140821    201408201043844    0.0201408141044090    1.020140812    201408111044090    2.020140816    20140815    201408171044090    0.0201408211044264    0.0201408101044264    3.020140815    20140814    20140813    201408121044264    5.020140821    20140820    20140822    20140819    20140817    20140818

結果中uid = 1043736 的一共登錄了7天,其中可以拆分成三個連續的登錄模塊,分別是連續登錄1天、2天和4天

    


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM