前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >hive sql(九)—— 访问/api/user/login接口的top10的ip地址

hive sql(九)—— 访问/api/user/login接口的top10的ip地址

作者头像
大数据最后一公里
发布2021-08-05 10:18:04
6690
发布2021-08-05 10:18:04
举报
文章被收录于专栏:大数据最后一公里

需求

代码语言:javascript
复制
有一张表,其中一个字段是由时间、接口、ip和其他字段组成的
求11月9号下午14点(14-15点),访问/api/user/login接口的top10的ip地址

建表语句

代码语言:javascript
复制
create table log(
    log_detail string
)
ROW format delimited FIELDS TERMINATED BY "\t"
;

数据

代码语言:javascript
复制
insert overwrite table log values
("2016-11-09 14:22:05 /api/user/login 110.23.5.33 a *"),
("2016-11-09 11:23:10 /api/user/detail 57.3.2.16 a *"),
("2016-11-09 14:59:40 /api/user/login 200.6.5.166 a *"),
("2016-11-09 14:22:05 /api/user/login 110.23.5.34 a *"),
("2016-11-09 14:22:05 /api/user/login 110.23.5.34 a *"),
("2016-11-09 14:22:05 /api/user/login 110.23.5.34 a *"),
("2016-11-09 11:23:10 /api/user/detail 57.3.2.16 a *"),
("2016-11-09 23:59:40 /api/user/login 200.6.5.166 a *"),
("2016-11-09 14:22:05 /api/user/login 110.23.5.34 a *"),
("2016-11-09 11:23:10 /api/user/detail 57.3.2.16 a *"),
("2016-11-09 23:59:40 /api/user/login 200.6.5.166 a *"),
("2016-11-09 14:22:05 /api/user/login 110.23.5.35 a *"),
("2016-11-09 14:23:10 /api/user/detail 57.3.2.16 a *"),
("2016-11-09 23:59:40 /api/user/login 200.6.5.166 a *"),
("2016-11-09 14:59:40 /api/user/login 200.6.5.166 a *"),
("2016-11-09 14:59:40 /api/user/login 200.6.5.166 a *");

实现

代码语言:javascript
复制
select
    t2.interface,
    t2.ip,
    t2.ip_visit_count,
    row_number() over( order by t2.ip_visit_count desc) as rk
from
    (select
        t1.interface,
        t1.ip,
        count(*) as ip_visit_count
    from
        (select
            split(log_detail," ")[0] as rq,
            split(log_detail," ")[1] as hour,
            split(log_detail," ")[2] as interface,
            split(log_detail," ")[3] as ip
        from
            log
        )t1
    where t1.interface = "/api/user/login"
        and date_format(t1.rq,"yyyy-MM-dd")= "2016-11-09" 
        and substring(t1.hour,0,2) >= 14
        and substring(t1.hour,0,2) <= 15
    group by t1.interface,t1.ip
    limit 10
    )t2
;

结果

代码语言:javascript
复制
Total MapReduce CPU Time Spent: 7 seconds 110 msec
OK
t2.interface  t2.ip  t2.ip_visit_count  rk
/api/user/login  110.23.5.34  4  1
/api/user/login  200.6.5.166  3  2
/api/user/login  110.23.5.33  1  3
/api/user/login  110.23.5.35  1  4
Time taken: 48.843 seconds, Fetched: 4 row(s)

分析

代码语言:javascript
复制
1、分析需求,需要时间、接口、ip三个字段
2、观察字符串的格式,选择合适的分割符切割
3、使用split函数切割字符串,将一列转换为三列
4、根据ip分组,统计每个ip的个数,这里group by时,需要group by t1.interface,t1.ip这样写
5、全局排序,需要开窗,开窗时不需要指定分区键,即不需要partition by
6、如下扩展对观察数据、切割、取数,需要注意,明确每一步操作的结果是什么

扩展

代码语言:javascript
复制
#split切割、数组取数
select
  split(log_detail," ")[0] as time,
    split(log_detail," ")[1] as interface,
    split(log_detail," ")[2] as ip
from
    log
OK
#这里结果并不对,观察数据,切割会将时间切成两部分,所以如上实现部分sql是正确的
#结果
time  interface  ip
2016-11-09  14:22:05  /api/user/login
2016-11-09  11:23:10  /api/user/detail
2016-11-09  14:59:40  /api/user/login
2016-11-09  14:22:05  /api/user/login
2016-11-09  14:22:05  /api/user/login
2016-11-09  14:22:05  /api/user/login
2016-11-09  11:23:10  /api/user/detail
2016-11-09  23:59:40  /api/user/login
2016-11-09  14:22:05  /api/user/login
2016-11-09  11:23:10  /api/user/detail
2016-11-09  23:59:40  /api/user/login
2016-11-09  14:22:05  /api/user/login
2016-11-09  14:23:10  /api/user/detail
2016-11-09  23:59:40  /api/user/login
2016-11-09  14:59:40  /api/user/login
2016-11-09  14:59:40  /api/user/login
Time taken: 0.3 seconds, Fetched: 16 row(s)

where date_format(t1.time,"yyyy-MM-dd HH") >= concat(year(current_date()),"-","11-09 14")
          and
          date_format(t1.time,"yyyy-MM-dd HH") <= concat(year(current_date()),"-","11-09 15")
          and
          ip = "/api/user/login"
          
#关于排序
因为最后需要全局排序,topn序号,那么如何选择排序时机

#测试一(没有达到预期的结果)
在group by时对ip_visit_count 降序排序,这时也是全局排序,但是在row_number()Over()开窗时,默认是升序
hive (default)> select
              >     t2.interface,
              >     t2.ip,
              >     t2.ip_visit_count,
              >     row_number() over() as rk
              > from
              >     (select
              >         t1.interface,
              >         t1.ip,
              >         count(*) as ip_visit_count
              >     from
              >         (select
              >             split(log_detail," ")[0] as rq,
              >             split(log_detail," ")[1] as hour,
              >             split(log_detail," ")[2] as interface,
              >             split(log_detail," ")[3] as ip
              >         from
              >             log
              >         )t1
              >     where t1.interface = "/api/user/login"
              >         and date_format(t1.rq,"yyyy-MM-dd")= "2016-11-09" 
              >         and substring(t1.hour,0,2) >= 14
              >         and substring(t1.hour,0,2) <= 15
              >     group by t1.interface,t1.ip
              >     order by ip_visit_count desc
              >     limit 10
              >     )t2
              > ;

Total MapReduce CPU Time Spent: 7 seconds 100 msec
OK
t2.interface  t2.ip  t2.ip_visit_count  rk
/api/user/login  110.23.5.33  1  1
/api/user/login  110.23.5.35  1  2
/api/user/login  200.6.5.166  3  3
/api/user/login  110.23.5.34  4  4

还有其他测试情况,篇幅有限,就不展示了

总结一下:
1、第一次排序和最终排序字段不冲突是可以的
2、如果第一次排序和最终排序实现目标一致,那么最后排序即可

知识点

代码语言:javascript
复制
1、split(字符串,分割符):使用分割符切割字符串,返回一个数组
2、row_number():row_number是基于over()开窗函数的一个不重复的序号,如上结果所示,即便结果相同,也会顺延,序号自增
3、substring(字符串,起始位置,步长):根据起始位置和步长切割字符串
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-07-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 大数据最后一公里 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档