数据分析-Hive学习 Day4

目标:
1、掌握hive基础语法、常用函数及其组合使用
2、掌握一些基本业务指标的分析思路与实现技巧

一、基础语法

1、SELECT ... A... FORM ...B... WHERE ...C...

1)某次经营活动中,商家发起了“异性拼团购”,试着针对某个地区的用户进行推广,找出匹配用户。

"选出城市在北京,性别位女的10个用户名"
select user_name
from user_info
where city='beijing' and sex='female'
limit 10;

注意:如果该表是一个分区表,则where条件中必须对分区字段进行限制

2)选出在2018年12月31日,购买的商品品类是food的用户名、购买数量、支付金额

select user_name
    ,piece
    ,pay_amount
from user_trade
where dt='2018-12-31' and goods_category='food';

2、GROUP BY(分类汇总)

3)试着对本公司2019年第一季度商品的热度与价值度进行分析。
"2019年一月到三月,每个品类有多少人购买,累计金额是多少"

    SELECT goods_category
        ,count(user_name) as user_num
        ,sum(pay_amount) as total_amount
    from user_trade
    WHERE dt between '2019-01-01' and '2019-03-31'
    group by goods_category

常用的聚会函数:
1、count():计数  count(distinct...)去重计数
2、sum():求和
3、avg():平均值
4、max():最大值
5、min():最小值

GROUP BY ... HAVING(分类汇总过滤)

4)找出在2019年4月支付金额超过5万元的用户,给这些VIP用户赠送优惠券

    SELECT user_name,sum(pay_amount) as total_amount
    from user_trade
    WHERE dt between '2019-04-01' and '2019-04-30'
    group by user_name
    HAVING sum(pay_amount)>50000;

3、ORDER BY(排序)

5)2019年4月,支付金额最多的TOP5用户

    SELECT user_name,sum(pay_amount) as total_amount
    from user_trade
    WHERE dt between '2019-04-01' and '2019-04-30'
    group by user_name
    order by total_amount desc
    limit 5;
    (由于执行顺序的原因,ORDER BY 后面要使用重新定义的列名进行排序,具体执行顺序参考MySQL)

    ASC:升序(默认) DESC:降序
    对多个字段进行排序:ORDER BY A ASC, B DESC,每个字段都要指定升序或者降序

二、常用函数

查看Hive中的函数:show functions;
查看具体函数的用法:1)desc function 函数名;2)desc function extended函数名;

1、如何把时间戳转化为日期(from_unixtime)?

6)

SELECT pay_time,
            from_unixtime(pay_time,'yyyy-MM-dd hh:mm:ss')
    from user_trade
    WHERE dt='2019-04-09'

from_unixtime(bigint unixtime,string format):将时间戳转化为指定格式的日期
format:
1.yyyy-MM-dd hh:mm:ss
2.yyyy-MM-dd hh
3.yyyy-MM-dd hh:mm
4.yyyyMMdd
拓展:把日期转化为时间戳:unix——timestamp(string date)

2、如何计算日期间隔?(datediff 函数)

7)用户的首次激活时间,与2019年5月1日的日期间隔。

SELECT user_name
         ,datediff('2019-05-01',to_date(firstactivetime))
 from user_info
 limit 10;

datediff(string enddate,string startdate):结束日期减去开始日期的天数

拓展:日期增加函数(增加天数)、减少函数(减少天数) —— date_add、date_sub(类型要是string类型的)
date_add(string startdate,int days)、date_sub(string startdate,int days)

3、条件函数(case when 和 if 函数)

case when 函数

8)统计以下四个年龄段20岁以下、20-30岁、30-40岁、40岁以上的用户数

SELECT
        case 
        when age<20 then '20岁以下'
        when  age<30 then '20-30岁'
        when  age<40 then '30-40岁'
        else '40岁以上' end as age_type,
        count(distinct  user_id) as user_num
    from user_info
    group by ( case 
        when age<20 then '20岁以下'
        when  age<30 then '20-30岁'
        when  age<40 then '30-40岁'
        else '40岁以上' end )

case when 的时候不用加group by,只有在聚合函数的时候才需要group by

if 函数

9)统计每个性别的用户等级高低分布情况(假设level大于5为高级,注意列名不能使用中文的)

SELECT sex,
       if(level>5,'高级','低级') as level_type,
       count(distinct user_id) as user_num
from user_info
group by sex,
if(level>5,'高级','低级');

4、字符串函数(substr 和 substring 函数)

10)分析每个月都拉新情况

    select substring(firstactivetime,1,7) as month
            ,count(distinct user_id) as user_num
    from user_info
    group by substring(firstactivetime,1,7);

substring(stringA,INT start,int len),substr(stringA,INT start,int len),截取起始位置和截取长度

json文本格式解析函数

extra1需要解析json字段,然后用$.key取出想要获取的value;
extra2使用的是中括号加引号的方式进行字段提取和分组;
两种写法要看字段类型的不同采取不同的方式

11)求不同手机品牌的用户数

    extra1(string):
    {"systemtype":"ios","education":"master","marriage_status":"1","phonebrand":"iphoneX"}
    
    extra2(map):
    {"systemtype":"ios","education":"master","marriage_status":"1","phonebrand":"iphone X"}



第一种情况:

 select get_json_object(extra1,'$.phonebrand') as phone_brand
     ,count(distinct user_id) as user_num
 from user_info
 group by  get_json_object(extra1,'$.phonebrand');


第二种情况:

 select extra2["phonebrand"] as phone_brand
     ,count(distinct user_id) as user_num
 from user_info
 group by  extra2["phonebrand"];


 extra1需要解析json字段,然后用$.key取出想要获取的value;
 extra2使用的是中括号加引号的方式进行字段提取和分组;
 两种写法要看字段类型的不同采取不同的方式

5、聚合统计函数

12)ELLA用户的2018年的平均每次支付金额,以及2018年最大的支付日期和最小的支付日期的间隔

SELECT  AVG(pay_amount),
        max(from_unixtime(pay_time,'yyyy-MM-dd')),
        min(from_unixtime(pay_time,'yyyy-MM-dd')),
        datediff(max(from_unixtime(pay_time,'yyyy-MM-dd')), min(from_unixtime(pay_time,'yyyy-MM-dd')))
from user_trade
WHERE substr(dt,1,4)='2018' and user_name='ELLA'


#如果要使用user_name,则要多加group by进行分组,having后用不了本题的限制条件

SELECT  user_name,
        AVG(pay_amount),
        max(from_unixtime(pay_time,'yyyy-MM-dd')),
        min(from_unixtime(pay_time,'yyyy-MM-dd'))
from user_trade
WHERE substr(dt,1,4)='2018'
GROUP BY user_name

三、重点练习

13)2018年购买的商品品类在两个以上的用户数

   步骤一:

    SELECT user_name,count(distinct goods_category)
    from user_trade
    where substr(dt,1,4)='2018'
    group by user_name
    having count(distinct goods_category)>=2;


   步骤二: 

    select count(a.user_name)
    from
        (SELECT user_name,count(distinct goods_category)
        from user_trade
        where substr(dt,1,4)='2018'
        group by user_name
        having count(distinct goods_category)>=2) as a

步骤总结:
1、先求出每个人购买的商品品类书
2、筛选出购买商品品类书大于2的用户
3、统计符合条件的用户有多少个

14)用户激活时间在2018年,年龄段在20-30岁和30-40岁的婚姻情况分布

错误方法(也能得出正确的结果,只是计算方式会比较慢): 
    select b.age_type,count(distinct b.user_id),if(b.marriage_status=1,"已婚","未婚")   
    from
    (select user_id
            ,user_name
            ,(case 
                when age<20 then "20岁以下"
                when age>=20 and age<30 then "20-30岁"
                when age>=30 and age<40 then "30-40岁"
                else '40岁以上'
                end) as age_type
            ,extra2["marriage_status"] as marriage_status
    from user_info
    where year(firstactivetime)='2018' 
    group by user_id
            ,user_name
            ,(case 
            when age<20 then "20岁以下"
            when age>=20 and age<30 then "20-30岁"
            when age>=30 and age<40 then "30-40岁"
            else '40岁以上'
            end)
            ,extra2["marriage_status"])as b
    where age_type in ("20-30岁", "30-40岁")
    group by b.age_type,if(b.marriage_status=1,"已婚","未婚")


正确方式:
    select b.age_type,count(distinct b.user_id),if(b.marriage_status=1,"已婚","未婚")     
    from
         (select user_id
            ,user_name
            ,(case 
                when age<20 then "20岁以下"
                when age>=20 and age<30 then "20-30岁"
                when age>=30 and age<40 then "30-40岁"
                else '40岁以上'
                end) as age_type
            ,extra2["marriage_status"] as marriage_status
        from user_info
        where year(firstactivetime)='2018' )as b
    where age_type in ("20-30岁", "30-40岁")
    group by b.age_type,if(b.marriage_status=1,"已婚","未婚")

步骤总结:
1、先选出激活时间在2018年的用户,并把他们所在的年龄段计算好,并提取出婚姻状况;
如何select后面没有进行聚合,则可以不用使用group by,直接使用where进行过滤就可以;
2、取出年龄段在20-30岁和30-40岁的用户,把他们的婚姻状况转义成可理解的说明;
3、聚合计算,针对年龄段,婚姻状况的聚合



 

你可能感兴趣的:(hive,数据分析,学习)