美文网首页SQL
HiveSQL核心技能之常用函数

HiveSQL核心技能之常用函数

作者: 让数据告诉你 | 来源:发表于2021-01-27 13:49 被阅读0次

    目标:
    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<string,string>):
        {"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、聚合计算,针对年龄段,婚姻状况的聚合

    相关文章

      网友评论

        本文标题:HiveSQL核心技能之常用函数

        本文链接:https://www.haomeiwen.com/subject/mhqazktx.html