LZ名約山炮

博客园 首页 新随笔 联系 订阅 管理

第 1 题 连续问题

  如下数据为蚂蚁森林中用户领取的减少碳排放量

id dt lowcarbon
1001 2021-12-12 123
1002 2021-12-12 45
1001 2021-12-13 43
1001 2021-12-13 45
1001 2021-12-13 23
1002 2021-12-14 45
1001 2021-12-14 230
1002 2021-12-15 45
1001 2021-12-15 23
… …

  找出连续 3 天及以上减少碳排放量在 100 以上的用户

第 2 题 分组问题

  如下为电商公司用户访问时间数据

id ts(秒)
1001 17523641234
1001 17523641256
1002 17523641278
1001 17523641334
1002 17523641434
1001 17523641534
1001 17523641544
1002 17523641634
1001 17523641638
1001 17523641654

  某个用户连续的访问记录如果时间间隔小于 60 秒,则分为同一个组,结果为:

id ts(秒) group
1001 17523641234 1
1001 17523641256 1
1001 17523641334 2
1001 17523641534 3
1001 17523641544 3
1001 17523641638 4
1001 17523641654 4
1002 17523641278 1
1002 17523641434 2
1002 17523641634 3

第 3 题 间隔连续问题

  某游戏公司记录的用户每日登录数据

id dt
1001 2021-12-12
1002 2021-12-12
1001 2021-12-13
1001 2021-12-14
1001 2021-12-16
1002 2021-12-16
1001 2021-12-19
1002 2021-12-17
1001 2021-12-20

  计算每个用户最大的连续登录天数,可以间隔一天。解释:如果一个用户在 1,3,5,6 登录游戏,则视为连续 6 天登录。

第 4 题 打折日期交叉问题

  如下为平台商品促销数据:字段为品牌,打折开始日期,打折结束日期

brand stt edt
oppo 2021-06-05 2021-06-09
oppo 2021-06-11 2021-06-21
vivo 2021-06-05 2021-06-15
vivo 2021-06-09 2021-06-21
redmi 2021-06-05 2021-06-21
redmi 2021-06-09 2021-06-15
redmi 2021-06-17 2021-06-26
huawei 2021-06-05 2021-06-26
huawei 2021-06-09 2021-06-15
huawei 2021-06-17 2021-06-21

  计算每个品牌总的打折销售天数,注意其中的交叉日期,比如 vivo 品牌,第一次活动时间为 2021-06-05 到 2021-06-15,第二次活动时间为 2021-06-09 到 2021-06-21 其中 9 号到 15号为重复天数,只统计一次,即 vivo 总打折天数为 2021-06-05 到 2021-06-21 共计 17 天。

第 5 题 同时在线问题

  如下为某直播平台主播开播及关播时间,根据该数据计算出平台最高峰同时在线的主播人数。

id stt edt
1001 2021-06-14 12:12:12 2021-06-14 18:12:12
1003 2021-06-14 13:12:12 2021-06-14 16:12:12
1004 2021-06-14 13:15:12 2021-06-14 20:12:12
1002 2021-06-14 15:12:12 2021-06-14 16:12:12
1005 2021-06-14 15:18:12 2021-06-14 20:12:12
1001 2021-06-14 20:12:12 2021-06-14 23:12:12
1006 2021-06-14 21:12:12 2021-06-14 23:15:12
1007 2021-06-14 22:12:12 2021-06-14 23:10:12

答案:自己一定要先做,不要直接看答案!!!

第一题:

  1)按照用户ID以时间字段分组,计算每个用户单日减少的碳排放量大于100的

select id,
       dt,
       sum(lowcarbon) lowcarbon
from test1
group by id,dt
having lowcarbon > 100;t1

  2)等差数列:两个等差数列若等差相同,则相同位置的数列相减得到的结果相同
    按照用户分组,同时按照时间排序,计算每条数据的Rank值

select id,
       dt,
       lowcarbon,
       rank() over(partition by id order by dt) rk
from t1;t2

  3)将每行数据中的日期减去Rank值

select id,
       dt,
       lowcarbon,
       date_sub(dt,rk) flag
from t2;t3

  4)按照用户以及flag分组,找出记录大于等于3条的

select id,
       flag,
       count(*) num
from t3
group by id,flag
having num >= 3;

  5)最终的HQL

select id,
       flag,
       count(*) num
from (
    select id,
           dt,
           lowcarbon,
           date_sub(dt,rk) flag
    from (
        select id,
               dt,
               lowcarbon,
               rank() over(partition by id order by dt) rk
        from (
            select id,
                   dt,
                   sum(lowcarbon) lowcarbon
            from test1
            group by id,dt
            having lowcarbon > 100
        ) t1
    ) t2
) t3
group by id,flag
having num >= 3;

第二题:

  1)将上一行时间数据下移

select id,
       ts,
       lag(ts,1,0) over(partition by id order by ts) lagts
from test2;t1

  2)将当前行的时间减去上一行的时间

select id,
       ts,
       ts-lagts diffts
from t1;t2

  3)每个用户范围内从第一行到当前行,判断diffts是否大于等于60,若diffts>=60,则加1,否则不变

select id,
       ts,
       sum(if(diffts>=60,1,0)) over(partition by id order by ts) groupid
from t2;t3

  4)最终的HQL

select id,
       ts,
       sum(if(diffts>=60,1,0)) over(partition by id order by ts) groupid
from (
    select id,
           ts,
           ts-lagts diffts
    from (
        select id,
               ts,
               lag(ts,1,0) over(partition by id order by ts) lagts
        from test2
    ) t1
) t2

第三题:

  1)将上一行时间下移

select id,
       dt,
       lag(dt,1,'1970-01-01') lagdt
from test3;t1

  2)将当前行时间减去上一行时间

select id,
       dt,
       datediff(dt,lagdt) diffdt
from t1;t2

  3)按照用户分组,并按时间排序,计算第一行到当前行大于2的数据总条数

select id,
       dt,
       sum(if(diffdt>2,1,0)) groupid
from t2;t3

  4)按照用户和groupid分组,求最大时间减去最小时间,然后加1

select id,
       groupid,
       (max(dt)-min(dt)+1) maxday
from t3;t4

  5)取连续登录天数的最大值

select id,
       max(maxday) loginmax
from t4
group by id

  6)最终的HQL

select id,
       max(maxday) loginmax
from (
    select id,
           groupid,
           (max(dt)-min(dt)+1) maxday
    from (
        select id,
               dt,
               sum(if(diffdt>2,1,0)) groupid
        from (
            select id,
                   dt,
                   datediff(dt,lagdt) diffdt
            from (
                select id,
                       dt,
                       lag(dt,1,'1970-01-01') lagdt
                from test3
            ) t1
        ) t2
    ) t3
) t4
group by id

第四题:

  1)将当前行以前的数据中最大的edt放置当前行

select id,
       stt,
       edt,
       max(edt) over(partition by id order by stt rows unbounded preceding and 1 preceding) maxEdt
from test4;t1

  2)比较开始时间与移动下来的时间,若开始时间大,则不需要操作,否则,需要将移动下来的时间加1替换当前行的开始时间,若第一行数据,maxEdt为null,不需要操作

select id,
       if(maxEdt is null,stt,if(stt>maxEdt,stt,date_add(maxEdt,1))) stt,
       edt
from t1;t2

  3)将每行数据中的结束日期减去开始日期

select id,
       datediff(edt,stt) day
from t2;t3

  4)按照品牌分组,计算每条数据加1的总和

select id,
       sum(if(day>=0,day+1,0)) days
from t3
group by id;

  5)最终的HQL

select id,
       sum(if(day>=0,day+1,0)) days
from (
    select id,
           datediff(edt,stt) day
    from (
        select id,
               if(maxEdt is null,stt,if(stt>maxEdt,stt,date_add(maxEdt,1))) stt,
               edt
        from (
            select id,
                   stt,
                   edt,
                   max(edt) over(partition by id order by stt rows unbounded preceding and 1 preceding) maxEdt
            from test4
        ) t1
    ) t2
) t3
group by id;

第五题:

  1)对数据分类,在开始时间后添加1,表示有主播上线,同时在关闭时间后添加-1,表示有主播下线

select id,
       stt dt,
       1 p
from test5
union
select id,
       edt dt,
       -1 p
from test5;t1

  2)按照时间排序,计算累加人数

select id,
       dt,
       sum(p) over(order by dt) sum_p
from t1;t2

  3)找出同时在线人数最大值

select max(sum_p)
from t2;

  4)最终的HQL

select max(sum_p)
from (
    select id,
           dt,
           sum(p) over(order by dt) sum_p
    from (
        select id,
               stt dt,
               1 p
        from test5
        union
        select id,
               edt dt,
               -1 p
        from test5
    ) t1
) t2;
posted on 2021-08-19 21:30  LZ名約山炮  阅读(648)  评论(0编辑  收藏  举报