SQL170. 某店铺的各商品毛利率及店铺整体毛利率
描述
商品信息表tb_product_info
id | product_id | shop_id | tag | in_price | quantity | release_time |
1 | 8001 | 901 | 家电 | 6000 | 100 | 2020-01-01 10:00:00 |
2 | 8002 | 902 | 家电 | 12000 | 50 | 2020-01-01 10:00:00 |
3 | 8003 | 901 | 3C数码 | 12000 | 50 | 2020-01-01 10:00:00 |
订单总表tb_order_overall
id | order_id | uid | event_time | total_amount | total_cnt | status |
1 | 301001 | 101 | 2021-10-01 10:00:00 | 30000 | 3 | 1 |
2 | 301002 | 102 | 2021-10-01 11:00:00 | 23900 | 2 | 1 |
3 | 301003 | 103 | 2021-10-02 10:00:00 | 31000 | 2 | 1 |
id | order_id | product_id | price | cnt |
1 | 301001 | 8001 | 8500 | 2 |
2 | 301001 | 8002 | 15000 | 1 |
3 | 301002 | 8001 | 8500 | 1 |
4 | 301002 | 8002 | 16000 | 1 |
5 | 301003 | 8002 | 14000 | 1 |
6 | 301003 | 8003 | 18000 | 1 |
场景逻辑说明:
用户将购物车中多件商品一起下单时,订单总表会生成一个订单(但此时未付款,status-订单状态为0表示待付款),在订单明细表生成该订单中每个商品的信息;
当用户支付完成时,在订单总表修改对应订单记录的status-订单状态为1表示已付款;
若用户退货退款,在订单总表生成一条交易总金额为负值的记录(表示退款金额,订单号为退款单号,status-订单状态为2表示已退款)。
product_id | profit_rate |
店铺汇总 | 31.0% |
8001 | 29.4% |
8003 | 33.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; INSERT INTO tb_order_overall(order_id, uid, event_time, total_amount, total_cnt, `status`) VALUES (301001, 101, '2021-10-01 10:00:00', 30000, 3, 1), (301002, 102, '2021-10-01 11:00:00', 23900, 2, 1), (301003, 103, '2021-10-02 10:00:00', 31000, 2, 1); 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, '家电', 6000, 100, '2020-01-01 10:00:00'), (8002, 902, '家电', 12000, 50, '2020-01-01 10:00:00'), (8003, 901, '3C数码', 12000, 50, '2020-01-01 10:00:00'); INSERT INTO tb_order_detail(order_id, product_id, price, cnt) VALUES (301001, 8001, 8500, 2), (301001, 8002, 15000, 1), (301002, 8001, 8500, 1), (301002, 8002, 16000, 1), (301003, 8002, 14000, 1), (301003, 8003, 18000, 1);
输出:
店铺汇总|31.0% 8001|29.4% 8003|33.3%
Mysql 解法, 执行用时: 37ms, 内存消耗: 6396KB, 提交时间: 2022-01-03
select ifnull(product_id,'店铺汇总') product_id,concat(profit_rate,'%') profit_rate from ( select a.product_id,round((1-sum(in_price*cnt)/sum(price*cnt))*100,1) profit_rate from tb_order_detail as a left join tb_order_overall as b on a.order_id=b.order_id left join tb_product_info as c on c.product_id=a.product_id where c.shop_id=901 and status=1 and date_format(event_time,'%Y%m')>='202110' group by a.product_id with rollup having profit_rate>24.9 or a.product_id is null) as d order by profit_rate
Mysql 解法, 执行用时: 37ms, 内存消耗: 6400KB, 提交时间: 2022-02-10
select '店铺汇总' AS product_id ,concat(round((1-(SUM(in_price*cnt) / SUM(price*cnt)))*100,1),"%") FROM tb_order_detail AS o LEFT JOIN tb_order_overall AS oo ON o.order_id = oo.order_id LEFT JOIN tb_product_info AS p ON o.product_id = p.product_id WHERE TIMESTAMPDIFF(day,"2021-09-30",event_time)>0 and p.shop_id = 901 GROUP BY p.shop_id union all SELECT product_id, concat(round(rate*100,1),"%") FROM (SELECT o.product_id AS product_id , (1-(sum(in_price)*sum(cnt))/(sum(price)*sum(cnt))) AS rate FROM tb_order_detail AS o LEFT JOIN tb_order_overall AS oo ON o.order_id = oo.order_id LEFT JOIN tb_product_info AS p ON o.product_id = p.product_id WHERE TIMESTAMPDIFF(day,"2021-09-30",event_time)>0 and p.shop_id = 901 GROUP BY o.product_id ORDER BY product_id) AS t WHERE rate>0.249
Mysql 解法, 执行用时: 37ms, 内存消耗: 6404KB, 提交时间: 2022-01-01
select '店铺汇总' product_id ,concat(round((1-sum(in_price*cnt)/sum(price*cnt))*100,1),'%') profit_rate from tb_order_detail tod left join tb_product_info tpi on tod.product_id = tpi.product_id left join tb_order_overall too on tod.order_id = too.order_id where too.status = 1 and date(event_time) >= '2021-10-01' and shop_id = 901 union all select tod.product_id ,concat(round((sum((price-in_price)*cnt)/sum(price*cnt))*100,1),'%') profit_rate from tb_order_detail tod left join tb_product_info tpi on tod.product_id = tpi.product_id left join tb_order_overall too on tod.order_id = too.order_id where too.status = 1 and date(event_time) >= '2021-10-01' and shop_id = 901 group by product_id having left(profit_rate,3) > 24.9 #order by product_id #注意最后group by和order by的时候product_id前不用加表名
Mysql 解法, 执行用时: 37ms, 内存消耗: 6408KB, 提交时间: 2022-01-22
SELECT '店铺汇总' as product_id, CONCAT(ROUND((1-SUM(in_price*cnt)/SUM(price*cnt))*100,1),'%') FROM tb_product_info tpi JOIN tb_order_detail tod ON tpi.product_id=tod.product_id JOIN tb_order_overall too ON too.order_id=tod.order_id WHERE shop_id='901' AND DATE(event_time)>='2021-10-01' UNION SELECT tpi.product_id, CONCAT(ROUND((1-sum(in_price*cnt)/sum(price*cnt))*100,1),'%') FROM tb_product_info tpi JOIN tb_order_detail tod ON tpi.product_id=tod.product_id JOIN tb_order_overall too ON too.order_id=tod.order_id WHERE shop_id='901' AND DATE(event_time)>='2021-10-01' GROUP BY product_id HAVING 1-sum(in_price*cnt)/sum(price*cnt)>0.249
Mysql 解法, 执行用时: 37ms, 内存消耗: 6408KB, 提交时间: 2021-12-04
select '店铺汇总' as product_id ,concat(round((1-sum(cnt*in_price)/ sum(cnt*price))*100,1),'%') as profit_rate from ( select c.shop_id ,a.product_id ,c.in_price ,a.price ,sum(a.cnt) as cnt from tb_order_detail a join tb_order_overall b on a.order_id=b.order_id join tb_product_info c on a.product_id=c.product_id where b.status='1' and c.shop_id='901' and b.event_time>='2021-10-01' group by a.product_id ,c.shop_id ,c.in_price ,a.price ) z group by shop_id union all select product_id ,concat(round((1-sum(cnt*in_price)/ sum(cnt*price))*100,1),'%') as profit_rate from ( select c.shop_id ,a.product_id ,c.in_price ,a.price ,sum(a.cnt) as cnt from tb_order_detail a join tb_order_overall b on a.order_id=b.order_id join tb_product_info c on a.product_id=c.product_id where b.status='1' and c.shop_id='901' and b.event_time>='2021-10-01' group by a.product_id ,c.shop_id ,c.in_price ,a.price ) g group by product_id having round((1-sum(cnt*in_price)/ sum(cnt*price))*100,1)>24.9