45. 复购率问题

文章目录

        • 题目需求
        • 思路一
        • 实现一
        • 扩展1
        • 实现一
        • 题目来源

题目需求

现有电商订单表(order_detail)如下。

order_id (订单id) user_id (用户id) product_id (商品id) price (售价) cnt (数量) order_date (下单时间)
1 1 1 5000 1 2022-01-01
2 1 3 5500 1 2022-01-02
3 1 7 35 2 2022-02-01
4 2 2 3800 3 2022-03-03

注:复购率指用户在一段时间内对某商品的重复购买比例,复购率越大,则反映出消费者对品牌的忠诚度就越高,也叫回头率

此处我们定义:某商品复购率 = 近90天内购买它至少两次的人数 ÷ 购买它的总人数

近90天指包含 最大日期(以订单详情表(order_detail)中最后的日期)在内的近90天。结果中复购率保留2位小数,并按复购率倒序、商品ID升序排序。

注意: 对 ‘最大日期’ 的理解, ‘最大日期’ 取所有 product_id 公共的 max(order_date),即每个 product_id 的 ‘最大日期’ 均相同

期望结果如下(截取部分):

product_id (商品id) crp (复购率)
3 1.00
9 1.00
8 0.50

思路一

45. 复购率问题_第1张图片

实现一

45. 复购率问题_第2张图片

-- 注意: 对 '最大日期' 的理解, '最大日期' 取所有 product_id 公共的 max(order_date)

with all_goods_nearly90 as (
    -- 2) 筛选出所有商品近90天的下单数据
    select user_id,
           product_id,
           order_date
    from (
             -- 1) 求所有商品公共的 last_order_date(取所有商品最后一次下单日期的最大值)、last_order_date_sub90
             select user_id,
                    product_id,
                    order_date,
                    -- 取所有商品最后一次下单日期的最大值 --> max(所有商品最后一次下单日期)
                    max(order_date) over ()                as last_order_date,
                    date_add(max(order_date) over (), -89) as last_order_date_sub90
             from order_detail_for45
         ) t1
    where last_order_date_sub90 <= t1.order_date
      and t1.order_date <= last_order_date
)
-- 5) 求复购率
select product_id,
--        denom, -- 分母
--        sum(flag) as molecule,  -- 分子(每个商品被多少人购买至少2次)
       cast(sum(flag) / denom as decimal(10, 2)) as cpr
from (
         -- 4) 筛选出某个人购买次数>=2的商品,标记flag为1,否则为0
         select user_id,
                product_id,
                denom,
                if(count(*) >= 2, 1, 0) as flag
         from (
                  select user_id,
                         product_id,
                         -- 3) 求购买每个商品的总人数
                         count(distinct user_id) over (partition by product_id) as denom
                  from all_goods_nearly90
              ) t2
         group by user_id, product_id, denom
     ) t3
group by product_id, denom
order by cpr desc, product_id;

扩展1

每个 product_id 有自己专属的 ‘最大日期’,即每个 product_id 的 ‘最大日期’ 可能不同

45. 复购率问题_第3张图片

实现一

-- 扩展1: 每个 product_id 有自己专属的最大日期

with all_goods_nearly90 as (
    -- 2) 筛选出所有商品近90天的下单数据
    select user_id,
           product_id,
           order_date
    from (
             -- 1) 求每个商品的 last_order_date(每个商品最后一次下单日期)、last_order_date_sub90
             select user_id,
                    product_id,
                    order_date,
                    -- 每个商品最后一次下单日期
                    first_value(order_date) over (partition by product_id order by order_date desc) as last_order_date,
                    -- 每个商品最后一次下单日期 - 89(近90天)
                    date_add(first_value(order_date) over (partition by product_id order by order_date desc),
                             -89)                                                                   as last_order_date_sub90
             from order_detail_for45
         ) t1
    where last_order_date_sub90 <= t1.order_date
      and t1.order_date <= last_order_date
)
-- 5) 求复购率
select product_id,
--        denom, -- 分母
--        sum(flag) as molecule,  -- 分子(每个商品被多少人购买至少2次)
       cast(sum(flag) / denom as decimal(10, 2)) as cpr
from (
         -- 4) 筛选出某个人购买次数>=2的商品,标记flag为1,否则为0
         select user_id,
                product_id,
                denom,
                if(count(*) >= 2, 1, 0) as flag
         from (
                  select user_id,
                         product_id,
                         -- 3) 求购买每个商品的总人数
                         count(distinct user_id) over (partition by product_id) as denom
                  from all_goods_nearly90
              ) t2
         group by user_id, product_id, denom
     ) t3
group by product_id, denom
order by cpr desc, product_id;

题目来源

http://practice.atguigu.cn/#/question/45/desc?qType=SQL

你可能感兴趣的:(#,HQL题目,数据库,sql,hive,大数据)