【Hive】Hive企业级实战案例

1、预备知识一:Hive时间函数

(1)时间格式大体分为两类:
标准日期格式:2015-08-31 00:04:37
Unixtimestamp:以格林威治时间为基准的Unix时间戳,该时间戳为以1970年1月1日0点0分0秒开始一直到现在此时此刻总的秒数或毫秒数,是一个long型的数据。
(2)hive自带提供了Unixtimestamp的函数方法
功能:将日期转换成对应的Unixtimestamp时间戳
举例:要计算2015-08-31 00:04:37与2015-09-02 00:00:00之间的时间间隔,需要先将日期格式转换成Unix时间戳,然后再相减得到最后的时间差。
使用的业务场景:
网站后台处理数据:其中有一个指标“停留时间”,“停留时间”是一个衡量网站质量好坏的重要的基准指标之一。
(3)测试hive自带的函数

select unix_timestamp("2017-05-20 12:00:00") from u_data limit 1;

下面这种格式无法运行转换出结果,是NULL:

select unix_timestamp("20170520 12:00:00") from u_data limit 1;

指定格式转化:

select unix_timestamp("20170520 12:00:00","yyyyMMdd HH:mm:ss") from u_data limit 1;

使用字段进行转换:

select unix_timestamp("time","yyyyMMdd HH:mm:ss") from u_data limit 1;

from_unixtime将Unix时间戳转换为标准的日期格式,比如:2017-05-20 12:00:00。

select from_unixtime(1495252800,"yyyyMMdd HH:mm:ss") from u_data limit 1;

或者

select from_unixtime(1495252800,"yyyy-MM-dd HH:mm:ss") from u_data limit 1;

2、预备知识二:case when

when用来直接判断这一列的值.
(1)需求:奖金comm这列如果是NULL的话就显示为0。

select empno,ename,
case 
when comm is null then 0 
else comm 
end 
from emp;

结果:

empno   ename   _c2
7369    SMITH   0.0
7499    ALLEN   300.0
7521    WARD    500.0
7566    JONES   0.0
7654    MARTIN  1400.0
7698    BLAKE   0.0
7782    CLARK   0.0
7788    SCOTT   0.0
7839    KING    0.0
7844    TURNER  0.0
7876    ADAMS   0.0
7900    JAMES   0.0
7902    FORD    0.0
7934    MILLER  0.0

(2)需求:员工不同的薪资显示不同的等级

select empno,ename,
case 
when sal<1000 then 'aaa' 
when sal>=1500 and sal<3000 then 'ccc' 
else 'ddd' 
end as new_sal 
from emp;

结果:

empno   ename   new_sal
7369    SMITH   aaa
7499    ALLEN   ccc
7521    WARD    ddd
7566    JONES   ccc
7654    MARTIN  ddd
7698    BLAKE   ccc
7782    CLARK   ccc
7788    SCOTT   ddd
7839    KING    ddd
7844    TURNER  ccc
7876    ADAMS   ddd
7900    JAMES   aaa
7902    FORD    ddd
7934    MILLER  ddd

3、预备知识三:Cast 方法

作用:数据类型的转换。

create table casttest as select empno e_no,ename e_name,cast(sal as string) new_sal from emp;

4、日志分析案例

分析流程
(1)需求分析
(2)数据采集
(3)数据清洗
(4)数据分析
(5)结果展示

(1)需求分析

预期结果统计:

日期 PV UV 登录人数 游客人数 平均访问时长 二跳率 独立IP

1)日期
按照日期进行分组,基于时间维度进行分析。
可以考虑建分区表,按给定日期分区。
2)PV
count(url)
3)UV
count(distinct(guid))
4)登录人数
登录人数代表的就是会员,使用账号登录的人。
登录之后会产生一个会员ID。
处理的时候可以看会员ID有没有值。
5)游客人数
会员ID没有值,但是guid有值,那就是游客访问的数据。
6)平均访问时长
当进入页面后,就会在后台开启一个会话,生成sessionID。
会话关闭代表sessionID失效,再次建立会话,会生成不同的sessionID。
将进入页面的第一条记录的时间戳和最后离开的最后一条记录的时间戳进行相减得到访问时长。
再对session进行分组,最后求得平均访问时长。
7)二跳率
一个用户在一个session会话中点击了大于等于2的网页数量。
一个页面就是一个PV,统计PV大于等于2的页面个数,再除以总的人数。
8)独立IP
distinct(ip)
(2)数据采集
1)建库

create database yhd;

2)建源表

create table yhd_source(
id              string,
url             string,
referer         string,
keyword         string,
type            string,
guid            string,
pageId          string,
moduleId        string,
linkId          string,
attachedInfo    string,
sessionId       string,
trackerU        string,
trackerType     string,
ip              string,
trackerSrc      string,
cookie          string,
orderCode       string,
trackTime       string,
endUserId       string,
firstLink       string,
sessionViewNo   string,
productId       string,
curMerchantId   string,
provinceId      string,
cityId          string,
fee             string,
edmActivity     string,
edmEmail        string,
edmJobId        string,
ieVersion       string,
platform        string,
internalKeyword string,
resultSum       string,
currentPage     string,
linkPosition    string,
buttonPosition  string
)
partitioned by (date string)
row format delimited fields terminated by '\t'
stored as textfile;

3)加载数据

load data local inpath '/opt/datas/2015082818' into table yhd_source partition(date='2015082818');

(3)数据清洗

访问渠道:就是指访问的方式,通过什么方式进来访问网页的
比如:收藏夹、百度、手敲网页等等
一定是第一条记录的访问渠道值才有意义
案例中的trackerU就是指用户访问网站的访问渠道

1)建源表

create table session_info(
session_id string ,
guid string ,
trackerU string ,
landing_url string ,
landing_url_ref string ,
user_id string ,
pv string ,
stay_time string ,
min_trackTime string ,
ip string ,
provinceId string 
)
partitioned by (date string)
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' ;

2)建临时表一

create table session_tmp as 
select 
sessionId session_id,
max(guid) guid,
max(endUserId) user_id,
count(distinct url) pv,
(unix_timestamp(max(trackTime))-unix_timestamp(min(trackTime))) stay_time,
min(trackTime) min_trackTime,
max(ip) ip,
max(provinceId) provinceId
from yhd_source where date='2015082818' 
group by sessionId;

PV值:count(distinct url) pv获取每一个session的PV,最后进行累加统计总的PV。
访问时长:每个session都会有第一个记录和最后一个记录,用最后的记录减去第一个记录得到的就是这个session的停留时间。
3)建临时表二

create table track_tmp as 
select 
sessionId session_id,
trackTime trackTime,
url landing_url,
referer landing_url_ref,
trackerU trackerU
from yhd_source where date='2015082818';

从源表中的每条记录都获取track_tmp表的五个字段。通过将某sessionID的每一条记录的时间trackTime和session_tmp表的最小时间min_trackTime进行join,join上了后track_tmp表记录的时间就是这个sessionID第一条记录的时间。然后获取(trackerU string),(landing_url string),(landing_url_ref string)这三个字段。
4)向源表插入数据,即join的实现

insert overwrite table session_info partition(date='2015082818') 
select 
a.session_id session_id,
max(a.guid) guid,
max(b.trackerU) trackerU,
max(b.landing_url) landing_url,
max(b.landing_url_ref) landing_url_ref,
max(a.user_id) user_id,
max(a.pv) pv,
max(a.stay_time) stay_time,
max(a.min_trackTime) min_trackTime,
max(a.ip) ip,
max(a.provinceId) provinceId
from session_tmp a join track_tmp b on 
a.session_id = b.session_id and a.min_trackTime = b.trackTime 
group by a.session_id;

注:加上group by a.sessionId为了避免实际的数据产生差错率,产生误差
5)数据清洗流程总结

  1. 建两张临时表,实现join生成数据,再放入session_info表中。
  2. 需要获取trackerU、landing_url、landing_url_ref这三个字段。
  3. track_tmp表中的sessionId session_id,trackTime trackTime字段是为了实现join。
  4. track_tmp表将所有值拿出来,不按照session进行分组,可以理解为作为一个全的集合,来获取其中的子集合。
  5. 大表拆小表是工作中一种常用的手段。

(4)数据分析
1)建结果集表一

create table result1 as 
select 
date date,
sum(pv) PV,
count(distinct guid) UV,
count(distinct case when user_id is not null then guid else null end) login_user,
count(distinct case when user_id is null then guid else null end) visitor,
avg(stay_time) avg_time,
count(case when pv>=2 then session_id else null end)/count(session_id) second_jump,
count(distinct ip) IP
from session_info 
where date='2015082818' 
group by date;

2)查询结果集表一

select * from result1;

结果如下:

日期 PV UV 登录人数 游客人数 平均访问时长 二跳率 独立IP
2015082818 36420.0 23928 23928 0 49.74171774059963 0.25886201755838995 19174

发现游客人数为0,问题出在判断user_id is null的地方,源数据中user_id的位置不是null,而是一个’\n’。
3)建结果集表二

create table result2 as 
select 
date date,
sum(pv) PV,
count(distinct guid) UV,
count(distinct case when length(user_id)!=0 then guid else null end) login_user,
count(distinct case when length(user_id)==0 then guid else null end) visitor,
avg(stay_time) avg_time,
count(case when pv>=2 then session_id else null end)/count(session_id) second_jump,
count(distinct ip) IP
from session_info 
where date='2015082818' 
group by date;

4)查询结果集表二

select * from result2;

结果如下:

日期 PV UV 登录人数 游客人数 平均访问时长 二跳率 独立IP
2015082818 36420.0 23928 11586 12367 49.74171774059963 0.25886201755838995 19174

(5)后续思考
1)一般还会在数据分析之前将数据进行过滤,清洗脏数据,去除非法数据。
2)可以考虑先写几个简单的MapReduce程序进行数据的过滤。
3)大数据处理一要考虑简单性,二要考虑效率问题。
4)一般在实际的工作中,还可以建外部表来进行多部门协作完成大数据的处理。

发布了219 篇原创文章 · 获赞 603 · 访问量 129万+

猜你喜欢

转载自blog.csdn.net/gongxifacai_believe/article/details/95453082