列表

详情


SQL172. 10月的新户客单价和获客成本

描述

商品信息表tb_product_info

id product_id
shop_id tag int_ quantity release_time
1 8001 901 日用 60 1000 2020-01-01 10:00:00
2 8002 901 零食 140 500 2020-01-01 10:00:00
3 8003 901 零食 160 500 2020-01-01 10:00:00
4 8004 902 零食
130 500 2020-01-01 10:00:00
(product_id-商品ID, shop_id-店铺ID, tag-商品类别标签, in_price-进货价格, quantity-进货数量, release_time-上架时间)

订单总表tb_order_overall

id order_id uid event_time total_amount total_cnt status
1 301002 102 2021-10-01 11:00:00 235 2 1
2 301003 101 2021-10-02 10:00:00
300 2 1
3 301005 104 2021-10-03 10:00:00
160 1 1
(order_id-订单号, uid-用户ID, event_time-下单时间, total_amount-订单总金额, total_cnt-订单商品总件数, status-订单状态)

订单明细表tb_order_detail

id order_id product_id price cnt
1 301002 8001 85 1
2 301002
8003
180 1
3 301003
8004
140
1
4 301003
8003
180 1
5 301005
8003
180 1

(order_id-订单号, product_id-商品ID, price-商品单价, cnt-下单数量)


问题计算2021年10月商城里所有新用户的首单平均交易金额(客单价)和平均获客成本(保留一位小数)。

:订单的优惠金额 = 订单明细里的{该订单各商品单价×数量之和} - 订单总表里的{订单总金额} 。

输出示例
示例数据的输出结果如下
avg_amount avg_cost
231.7 23.3
解释:
2021年10月有3个新用户,102的首单为301002,订单金额为235,商品总金额为85+180=265,优惠金额为30;
101的首单为301003,订单金额为300,商品总金额为140+180=320,优惠金额为20;
104的首单为301005,订单金额为160,商品总金额为180,优惠金额为20;
平均首单客单价为(235+300+160)/3=231.7,平均获客成本为(30+20+20)/3=23.3

示例1

输入:

DROP TABLE IF EXISTS tb_order_overall;
CREATE TABLE tb_order_overall (
    id INT PRIMARY KEY AUTO_INCREMENT COMMENT '自增ID',
    order_id INT NOT NULL COMMENT '订单号',
    uid INT NOT NULL COMMENT '用户ID',
    event_time datetime COMMENT '下单时间',
    total_amount DECIMAL NOT NULL COMMENT '订单总金额',
    total_cnt INT NOT NULL COMMENT '订单商品总件数',
    `status` TINYINT NOT NULL COMMENT '订单状态'
) CHARACTER SET utf8 COLLATE utf8_bin;

DROP TABLE IF EXISTS tb_product_info;
CREATE TABLE tb_product_info (
    id INT PRIMARY KEY AUTO_INCREMENT COMMENT '自增ID',
    product_id INT NOT NULL COMMENT '商品ID',
    shop_id INT NOT NULL COMMENT '店铺ID',
    tag VARCHAR(12) COMMENT '商品类别标签',
    in_price DECIMAL NOT NULL COMMENT '进货价格',
    quantity INT NOT NULL COMMENT '进货数量',
    release_time datetime COMMENT '上架时间'
) CHARACTER SET utf8 COLLATE utf8_bin;

DROP TABLE IF EXISTS tb_order_detail;
CREATE TABLE tb_order_detail (
    id INT PRIMARY KEY AUTO_INCREMENT COMMENT '自增ID',
    order_id INT NOT NULL COMMENT '订单号',
    product_id INT NOT NULL COMMENT '商品ID',
    price DECIMAL NOT NULL COMMENT '商品单价',
    cnt INT NOT NULL COMMENT '下单数量'
) CHARACTER SET utf8 COLLATE utf8_bin;

INSERT INTO tb_product_info(product_id, shop_id, tag, in_price, quantity, release_time) VALUES
  (8001, 901, '日用', 60, 1000, '2020-01-01 10:00:00'),
  (8002, 901, '零食', 140, 500, '2020-01-01 10:00:00'),
  (8003, 901, '零食', 160, 500, '2020-01-01 10:00:00'),
  (8004, 902, '零食', 130, 500, '2020-01-01 10:00:00');

INSERT INTO tb_order_overall(order_id, uid, event_time, total_amount, total_cnt, `status`) VALUES
  (301002, 102, '2021-10-01 11:00:00', 235, 2, 1),
  (301003, 101, '2021-10-02 10:00:00', 300, 2, 1),
  (301005, 104, '2021-10-03 10:00:00', 160, 1, 1);

INSERT INTO tb_order_detail(order_id, product_id, price, cnt) VALUES
  (301002, 8001, 85, 1),
  (301002, 8003, 180, 1),
  (301003, 8004, 140, 1),
  (301003, 8003, 180, 1),
  (301005, 8003, 180, 1);

输出:

231.7|23.3

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

Mysql 解法, 执行用时: 37ms, 内存消耗: 6400KB, 提交时间: 2021-12-16

SELECT
    ROUND(SUM(total_amount) / COUNT(uid), 1) AS avg_amount,
    ROUND(SUM(firstly_amount - total_amount) / COUNT(uid), 1) AS avg_cost
FROM
    (SELECT
        uid,
        order_id,
        total_amount
    FROM 
        (SELECT
            *,
            RANK()OVER(PARTITION BY uid ORDER BY event_time) AS order_rank
        FROM tb_order_overall) AS t1
    WHERE
        order_rank = 1
        AND
        DATE_FORMAT(event_time, '%Y%m') = 202110) AS t2
JOIN
    (SELECT
        order_id,
        SUM(price * cnt) AS firstly_amount
    FROM tb_order_detail
    GROUP BY order_id) AS t3
ON t2.order_id = t3.order_id;

Mysql 解法, 执行用时: 37ms, 内存消耗: 6408KB, 提交时间: 2022-01-24

# 问题:请计算2021年10月商城里所有新用户的首单平均交易金额(客单价)和平均获客成本(保留一位小数)。

# 注:订单的优惠金额 = 订单明细里的{该订单各商品单价×数量之和} - 订单总表里的{订单总金额} 
# 解释:

# 2021年10月有3个新用户,102的首单为301002,订单金额为235,商品总金额为85+180=265,优惠金额为30;
# 101的首单为301003,订单金额为300,商品总金额为140+180=320,优惠金额为20;
# 104的首单为301005,订单金额为160,商品总金额为180,优惠金额为20;
# 平均首单客单价为(235+300+160)/3=231.7,平均获客成本为(30+20+20)/3=23.3

with a as(
SELECT uid,min(event_time) as reg_datetime
FROM tb_order_detail tod
JOIN tb_order_overall too
ON tod.order_id = too.order_id
GROUP BY uid
HAVING DATE_FORMAT(DATE(min(event_time)),'%Y-%m') = '2021-10')

select round(avg(total_amount),1) as avg_amount,round(avg(cost),1) as avg_cost
from(
    SELECT too.uid,total_amount,sum(price*cnt) - total_amount as cost
    FROM tb_order_detail tod
    JOIN tb_order_overall too
    ON tod.order_id = too.order_id
    JOIN a
    ON too.uid = a.uid and too.event_time = a.reg_datetime
    group by too.uid,total_amount) as b


Mysql 解法, 执行用时: 37ms, 内存消耗: 6408KB, 提交时间: 2022-01-23

#10月新用户
with a as
(select uid,total_amount,tb_order_overall.order_id,
sum(price*cnt) as total
from tb_order_overall,tb_order_detail
where tb_order_overall.order_id=tb_order_detail.order_id
and month(event_time)=10
group by tb_order_overall.order_id,uid,total_amount),
b as
#首单,且是新用户
(select uid,order_id from 
(select uid,order_id,event_time,
dense_rank()over(partition by uid order by event_time) as rk
from tb_order_overall)a1
where rk=1 and month(event_time)=10),
c as#10月新客户的首单信息
(select * from a 
where uid in (select uid from b) 
and order_id in (select order_id from b))
select round(avg(total_amount),1) as avg_amount,
round(avg(total-total_amount),1) as avg_cost
from c

Mysql 解法, 执行用时: 37ms, 内存消耗: 6416KB, 提交时间: 2022-01-21

# select round(avg(avg_a),1) avg_amount,round(avg(avg_in-avg_a),1) as avg_cost from
# (select uid,avg(total_amount) avg_a,sum(cnt*price) avg_in from
# (select uid,event_time,tod.order_id,total_amount,cnt,price,
# dense_rank() over(partition by uid order by event_time) timerank
# from tb_order_detail tod,tb_product_info tpi,tb_order_overall too
# where tod.product_id=tpi.product_id and tod.order_id=too.order_id
# and left(event_time,7) like '2021-10')a
# where timerank=1
# group by uid
# order by uid)b

select round(sum(total_amount)/count(distinct too.order_id),1) avg_amount
,round(sum(price-total_amount)/count(distinct  too.order_id),1) avg_cost
from tb_order_overall too
inner join (
  select order_id,sum(price*cnt) price
  from tb_order_detail
  group by order_id
  ) as t
on too.order_id=t.order_id
where date_format(event_time,'%Y-%m')='2021-10'
and (uid,date(event_time)) in (select uid,min(date(event_time)) from tb_order_overall group by uid)

Mysql 解法, 执行用时: 37ms, 内存消耗: 6428KB, 提交时间: 2022-01-22

select round(avg(total_amount),1) avg_amount,round(avg(sum_price-total_amount),1) avg_cost
from
(
        select 
        uid,event_time
        ,total_amount
        ,row_number() over(partition by uid order by event_time) rk
        ,sum(price*cnt) over(partition by order_id) sum_price
        ,status
        from tb_order_detail tod
        join tb_order_overall too
        using(order_id)
        where status = 1 
) t
where rk = 1
and date_format(event_time,'%Y-%m')='2021-10'