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 |
订单总表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 |
订单明细表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 |
avg_amount | avg_cost |
231.7 | 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'