zoukankan      html  css  js  c++  java
  • 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天

        
  • 相关阅读:
    Android高级控件(四)——VideoView 实现引导页播放视频欢迎效果,超级简单却十分的炫酷
    Android源代码文件夹结构说明
    IOS-Storyboard控制器切换之TabBar(3)
    若干排序算法简单汇总(一)
    Linux地址ping不通情况怎么办?
    pve三种操作方式
    Office Add-in 设计规范与最佳实践
    编辑您的代码
    持续集成
    人工智能到底能给我们带来什么?
  • 原文地址:https://www.cnblogs.com/juefan/p/3928966.html
Copyright © 2011-2022 走看看