hive sql 练习

数据和题目源:数据蛙https://www.jianshu.com/u/1f32f227da5f

建表:使用hive sql的CTAS 快速建表语法复制表到自己的数据库

create table frog_qing.ods_sales_orders as select * from adventure_ods.ods_sales_orders;
create table frog_qing.ods_cutomer as select * from adventure_ods.ods_customer;
  • ods_sales_orders表的列说明如下:


    1.PNG
  • ods_cutomer表的列说明如下:


    2.PNG

题目汇总

  • 题目一:每个用户截止到每月为止的最大交易金额和累计到该月的总交易金额,结果数据格式如下
  • 题目二:计算用户的回购率和复购率
  • 题目三:求用户号对应不同的产品]
  • 题目四:统计各个省份所属城市下最受欢迎的Top 3产品和其销量(不能出现有null)
  • 题目五:商品的销售数量top10,排名需考虑并列排名的情况
  • 题目六:计算累计和(统计2019年1-12月的累积销量,即1月为1月份的值,2月为1、2月份值的和,3月为1、2、3月份的和,12月为1-12月份值的和
  • 题目七计算客户平均购买一次商品的间隔时间
  • 题目八:查询最近前20%时间的订单信息
  1. 每个用户截止到每月为止的最大交易金额和累计到该月的总交易金额,结果数据格式如下
    1.1 先将日期转为By 年/月格式,按照客户和年月进行分组
    1.2 计算分组后的最大交易金额和累计总交易金额
select 
    b.customer_key,
    b.umonth,
    b.ucount,
    b.current_max,
    sum(b.sum_price) over(partition by b.customer_key order by b.umonth) as current_sum
from (
    select 
        customer_key,
        date_format(create_date, 'YYYY-MM-01') as umonth,
        count(sales_order_key) as ucount,
        max(unit_price) as current_max,
        sum(unit_price) as sum_price
    from ods_sales_orders
    group by customer_key,date_format(create_date, 'YYYY-MM-01')
) b
limit 50;
  1. 计算用户的回购率和复购率
    2.1 复购率,一个月内购买了多次的用户占总用户的比例
select 
    a.umonth,
    count(a.ucount) as user_c,
    sum(if(a.ucount>1, 1, 0))/count(ucount) as fugou
from (
    select 
        date_format(create_date, 'YYYY-MM-01') AS umonth,
        count(customer_key) as ucount
    from ods_sales_orders
    group by date_format(create_date, 'YYYY-MM-01'),customer_key
) a
group by a.umonth
limit 20;

2.2 回购率,当前月份购买且下个月份也购买的客户占当月所有月份客户比例,思路:现将当月数据和下个月数据进行连接,连接后按月分组计算回购人数和比例

select 
    a.umonth,
    count(a.customer_key) as pay_user,
    count(b.customer_key) as fg_user,
    concat((count(b.customer_key)/count(a.customer_key))*100,'%') as fg_rate
from (
    select 
        date_format(create_date, 'YYYY-MM-01') as umonth,
        customer_key
    from ods_sales_orders a
    group by date_format(create_date, 'YYYY-MM-01'),customer_key) a
left join (
    select 
        date_format(create_date, 'YYYY-MM-01') as umonth,
        customer_key
    from ods_sales_orders a
    group by date_format(create_date, 'YYYY-MM-01'),customer_key) b
on a.customer_key=b.customer_key 
and add_months(a.umonth,1)=b.umonth
group by a.umonth;
  1. 求用户号对应不同的产品,理解:求出用户第一次和第二次购买的产品
    注意点:
    3.1.1 lead()窗口函数求出窗口的后一个值,当为Null值时,使用where函数判断是否相等时会过滤掉这些null值,而我们需要保留这些null值,使用nvl()将null值转换,进行保留
    3.1.2 collect_set(字段)根据某个字段分组后,把分在一组的数据进行去重,去重后的数据按分组形成集合,默认分隔符','
    3.1.3 concat_ws('-',collect_set(xx)) 可将分组后的数据使用指定分隔符链接
  • 方法一、按照数据蛙答案修改,筛选出来购买大于两次的用户,且购买产品不同的用户和对应产品
with tmp as (
    select 
        a.customer_key,
        a.cpzl_zw,
        a.rk,
        a.second_cpzl,
        row_number() over(partition by customer_key order by rk) as rn
    from (
        select 
            customer_key,
            cpzl_zw,
            row_number() over(partition by customer_key order by create_date) as rk,
            lead(cpzl_zw,1, null) over(partition by customer_key order by create_date) as second_cpzl
        from ods_sales_orders
    ) a
    where a.cpzl_zw != a.second_cpzl
)
select concat(customer_key,'-',cpzl_zw, '-',second_cpzl),count(1)
from tmp
where tmp.rn < 2
limit 20;
  • 方法二、利用collect_set特性,保留了购买一次客户的产品和两次购买相同产品的客户
select 
    a.customer_key,
    count(1),
    concat(a.customer_key, '-',concat_ws('-', collect_set(a.cpzl_zw))) as product
from (
    select 
        customer_key,
        cpzl_zw,
        row_number() over(partition by customer_key order by create_date) as rn
    from ods_sales_orders
) a
where a.rn <3
group by a.customer_key
limit 20;
  1. 统计各个省份所属城市下最受欢迎的Top 3产品和其销量(不能出现有null)
    4.1 求出每个城市各产品的销量
select 
    b.chinese_city,
    a.cpzl_zw,
    count(a.sales_order_key) as sales
from ods_sales_orders a
left join ods_cutomer b
on a.customer_key = b.customer_key
group by b.chinese_city,a.cpzl_zw
limit 20;

4.2 求出按城市按产品销量的排名

select 
    c.chinese_city,
    c.cpzl_zw,
    c.sales,
    row_number() over(partition by c.chinese_city order by c.sales desc) rn
from (
    select 
        b.chinese_city,
        a.cpzl_zw,
        count(a.sales_order_key) as sales
    from ods_sales_orders a
    left join ods_cutomer b
    on a.customer_key = b.customer_key
    group by b.chinese_city,a.cpzl_zw
) c
where c.chinese_city is not null and c.chinese_city != 'null'
limit 20;

4.3 筛选每个城市top3的产品

select 
    d.chinese_city,
    d.cpzl_zw,
    d.sales,
    d.rn
from (
    select 
        c.chinese_city,
        c.cpzl_zw,
        c.sales,
        row_number() over(partition by c.chinese_city order by c.sales desc) rn
    from (
        select 
            b.chinese_city,
            a.cpzl_zw,
            count(a.sales_order_key) as sales
        from ods_sales_orders a
        left join ods_cutomer b
        on a.customer_key = b.customer_key
        group by b.chinese_city,a.cpzl_zw
    ) c
    where c.chinese_city is not null and c.chinese_city != 'null'
) d
where d.rn <4;
  1. 商品的销售数量top10,排名需考虑并列排名的情况
    5.1 计算每个产品的销量
select 
    cpzl_zw,
    count(1) as sales
from ods_sales_orders
group by cpzl_zw
limit 20;

5.2 按销量进行排名,筛选前10销量
DENSE_RANK() 生成数据项在分组中的排名,相同值序号一样,不跳过下个序号

select *
from (
    select 
        a.cpzl_zw,
        a.sales,
        dense_rank() over(order by a.sales) as rn
    from (
        select 
            cpzl_zw,
            count(1) as sales
        from ods_sales_orders
        group by cpzl_zw
    ) a
    ) b
where b.rn <=10;
  1. 计算累计和(统计2019年1-12月的累积销量,即1月为1月份的值,2月为1、2月份值的和,3月为1、2、3月份的和,12月为1-12月份值的和)
    6.1 计算每个月的销量
select 
    date_format(create_date, 'YYYY-MM-01') as month_date,
    COUNT(sales_order_key) as sale_amount
from ods_sales_orders
group by date_format(create_date, 'YYYY-MM-01');

6.2 计算累计销量
ORDER BY create_date 按月份对查询读取的记录进行排序,就是窗口范围内的排序

ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW 定义起点和终点,UNBOUNDED PRECEDING 为起点,表明从第一行开始, CURRENT ROW为默认值,就是这一句等于:ROWS UNBOUNDED PRECEDING PRECEDING:在前 N 行的意思,FOLLOWING:在后 N 行的意思。

select 
    a.month_date,
    a.sale_amount,
    sum(a.sale_amount) over(order by month_date asc ORDER BY create_date ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) as sale_amount_consum
from (
    select 
        date_format(create_date, 'YYYY-MM-01') as month_date,
        COUNT(sales_order_key) as sale_amount
    from ods_sales_orders
    group by date_format(create_date, 'YYYY-MM-01')
) a;
  1. 计算客户平均购买一次商品的间隔时间
    7.1 得出用户两次购买的时间,使用lead()函数
    LEAD(col,n,DEFAULT) 用于统计窗口内往下第n行值,第一个参数为列名,第二个参数为往下第n行(可选,默认为1),第三个参数为默认值(当往下第n行为NULL时候,取默认值,如不指定,则为NULL)所以使用LEAD (时间,1),取客户的时间,按照客户编号分组再按时间排序,所以使用over(partition by 客户编号 order by 时间)
select 
    customer_key,
    create_date,
    lead(create_date,1,null) over(partition by customer_key order by create_date) as next_date
from ods_sales_orders
limit 20;

7.2 计算两次购买时间差,再计算出每个客户的平均时间差

select 
    a.customer_key,
    avg(datediff(a.next_date, a.create_date)) as avg_days
from (
    select 
        customer_key,
        create_date,
        lead(create_date,1,'2019-01-01') over(partition by customer_key order by create_date) as next_date
    from ods_sales_orders
) a 
where datediff(a.next_date, a.create_date)>0
group by a.customer_key limit 20;
  1. 查询最近前20%即前1/5时间的订单信息
    8.1 将时间按降序分为5组,使用nitle()窗口函数将日期降序分位5组
select 
    *,
    ntile(5) over(order by create_date desc) gid
from ods_sales_orders limit 10;

8.2 取出时间分组为第一组的订单信息

select *
from (
    select 
        *,
        ntile(5) over(order by create_date desc) gid
    from ods_sales_orders
) a
where a.gid=1;
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 221,331评论 6 515
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,372评论 3 398
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 167,755评论 0 360
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,528评论 1 296
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,526评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,166评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,768评论 3 421
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,664评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,205评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,290评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,435评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,126评论 5 349
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,804评论 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,276评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,393评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,818评论 3 376
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,442评论 2 359

推荐阅读更多精彩内容

  • 背景 日常工作中有许多数据处理需求需要解决,在此之间,获得需求,用hive实现需求,最终完成任务。 题目 数据源在...
    xingxiliang阅读 547评论 0 0
  • 查询全体学生的学号与姓名 查询选修了课程的学生姓名 ----hive的group by 和集合函数 查询学生的总人...
    ForgetThatNight阅读 3,087评论 0 2
  • hive 日常数据需求(尽可能展示窗口函数的使用) 题目一:每个用户截止到每月为止的最大交易金额和累计到该月的总交...
    SongSir1阅读 1,385评论 0 4
  • 一、思维导图 二、准备工作 2.1使用工具 由于hive安装复杂,本项目使用金融数据分析案例第四篇《Hive初步学...
    dataTONG阅读 1,924评论 0 1
  • SQL1: domain time traffic(T)gifshow.com 2...
    吃货大米饭阅读 299评论 0 0