现有电商订单表(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 |
-- 注意: 对 '最大日期' 的理解, '最大日期' 取所有 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;
每个 product_id 有自己专属的 ‘最大日期’,即每个 product_id 的 ‘最大日期’ 可能不同
-- 扩展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