SQL173. 店铺901国庆期间的7日动销率和滞销率
描述
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 |
订单总表tb_order_overall
id | order_id | uid | event_time | total_amount | total_cnt | status |
1 | 301004 | 102 | 2021-09-30 10:00:00 | 170 | 1 | 1 |
2 | 301005 | 104 | 2021-10-01 10:00:00 | 160 | 1 | 1 |
3 | 301003 | 101 | 2021-10-02 10:00:00 | 300 | 2 | 1 |
4 | 301002 | 102 | 2021-10-03 11:00:00 | 235 | 2 | 1 |
订单明细表tb_order_detail
id | order_id | product_id | price | cnt |
1 | 301004 | 8002 | 180 | 1 |
2 | 301005 | 8002 | 170 | 1 |
3 | 301002 | 8001 | 85 | 1 |
4 | 301002 | 8003 | 180 | 1 |
5 | 301003 | 8002 | 150 | 1 |
6 | 301003 | 8003 | 180 | 1 |
dt | sale_rate | unsale_rate |
2021-10-01 | 0.333 | 0.667 |
2021-10-02 | 0.667 | 0.333 |
2021-10-03 | 1.000 | 0.000 |
示例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'); INSERT INTO tb_order_overall(order_id, uid, event_time, total_amount, total_cnt, `status`) VALUES (301004, 102, '2021-09-30 10:00:00', 170, 1, 1), (301005, 104, '2021-10-01 10:00:00', 160, 1, 1), (301003, 101, '2021-10-02 10:00:00', 300, 2, 1), (301002, 102, '2021-10-03 11:00:00', 235, 2, 1); INSERT INTO tb_order_detail(order_id, product_id, price, cnt) VALUES (301004, 8002, 180, 1), (301005, 8002, 170, 1), (301002, 8001, 85, 1), (301002, 8003, 180, 1), (301003, 8002, 150, 1), (301003, 8003, 180, 1);
输出:
2021-10-01|0.333|0.667 2021-10-02|0.667|0.333 2021-10-03|1.000|0.000
Mysql 解法, 执行用时: 37ms, 内存消耗: 6404KB, 提交时间: 2021-12-19
with t as ( select tod.order_id ,tod.product_id ,date(event_time) dt ,shop_id from tb_order_detail tod left join tb_order_overall too on tod.order_id = too.order_id left join tb_product_info tpi on tod.product_id = tpi.product_id where shop_id = 901 ) select dt,sale_rate,unsale_rate from( select '2021-10-01' dt ,round(sum(inde_1)/count(*),3) sale_rate ,round(1-sum(inde_1)/count(*),3) unsale_rate from ( select max(if(dt between '2021-09-25' and '2021-10-01',1,0)) inde_1 from t group by product_id ) t1 union all select '2021-10-02' dt ,round(sum(inde_2)/count(*),3) sale_rate ,round(1-sum(inde_2)/count(*),3) unsale_rate from ( select max(if(dt between '2021-09-26' and '2021-10-02',1,0)) inde_2 from t group by product_id ) t2 union all select '2021-10-03' dt ,round(sum(inde_3)/count(*),3) sale_rate ,round(1-sum(inde_3)/count(*),3) unsale_rate from ( select max(if(dt between '2021-09-27' and '2021-10-03',1,0)) inde_3 from t group by product_id ) t3 ) tt where tt.dt in (select distinct date(event_time) from tb_order_overall)
Mysql 解法, 执行用时: 37ms, 内存消耗: 6492KB, 提交时间: 2022-01-22
select dt1,round(count(distinct if(timestampdiff(day,dt,dt1) between 0 and 6, tb1.product_id,null))/count(distinct if(dt1>=date(release_time),tb3.product_id,null)),3) sale_rate, 1-round(count(distinct if(timestampdiff(day,dt,dt1) between 0 and 6, tb1.product_id,null))/count(distinct if(dt1>=date(release_time),tb3.product_id,null)),3) unsale_rate from (select date(event_time) dt1 from tb_order_overall having dt1 between '2021-10-01' and '2021-10-03') tb2 , (select b.product_id,date(event_time) dt from tb_order_overall a left join tb_order_detail b on a.order_id=b.order_id left join tb_product_info c on b.product_id=c.product_id where shop_id=901) tb1 left join tb_product_info tb3 on tb1.product_id=tb3.product_id where shop_id=901 group by dt1
Mysql 解法, 执行用时: 37ms, 内存消耗: 6504KB, 提交时间: 2022-01-25
with t as ( select date(event_time) dt from tb_order_overall where date(event_time) between '2021-10-01' and '2021-10-03' ), t1 as ( select date(event_time) dt, tod.product_id from tb_order_detail tod join tb_order_overall too on tod.order_id = too.order_id and status = 1 join tb_product_info tpi on tod.product_id = tpi.product_id and shop_id = '901' ), t2 as ( select date(event_time) dt, count(distinct case when datediff(date(event_time),date(release_time))>=0 then product_id end) sum_product from tb_product_info,tb_order_overall where shop_id = '901' group by dt ) select t.dt, round(count(distinct t1.product_id)/sum_product,3) as sale_rate, round(1-(count(DISTINCT t1.product_id)/sum_product),3) as unsale_rate from t left join t1 on datediff(t.dt,t1.dt) between 0 and 6 join t2 on t.dt = t2.dt group by 1 order by 1
Mysql 解法, 执行用时: 37ms, 内存消耗: 6512KB, 提交时间: 2021-12-18
SELECT dt, sale_rate, 1 - sale_rate as unsale_rate FROM ( SELECT dt, ROUND(MIN(sale_pid_cnt) / COUNT(all_pid), 3) as sale_rate FROM ( SELECT dt, COUNT(DISTINCT IF(shop_id!=901, NULL, product_id)) as sale_pid_cnt FROM ( SELECT DISTINCT DATE(event_time) as dt FROM tb_order_overall WHERE DATE(event_time) BETWEEN '2021-10-01' AND '2021-10-03' ) as t_dates LEFT JOIN ( SELECT DISTINCT DATE(event_time) as event_dt, product_id FROM tb_order_overall JOIN tb_order_detail USING(order_id) ) as t_dt_pid ON DATEDIFF(dt,event_dt) BETWEEN 0 AND 6 LEFT JOIN tb_product_info USING(product_id) group by dt) as t_dt_901_pid_cnt LEFT JOIN ( -- 店铺901每个商品上架日期 SELECT DATE(release_time) as release_dt, product_id as all_pid FROM tb_product_info WHERE shop_id=901 ) as t_release_dt ON dt >= release_dt # 当天店铺901已上架在售的商品 GROUP BY dt ) as t_dt_sr
Mysql 解法, 执行用时: 37ms, 内存消耗: 6548KB, 提交时间: 2021-12-17
select dt, round(count(distinct product_id)/(select count(product_id) from tb_product_info where shop_id = 901),3), round(1-count(distinct product_id)/(select count(product_id) from tb_product_info where shop_id = 901),3) from (select date(event_time) dt from tb_order_overall where date(event_time) between '2021-10-01' and '2021-10-03') a left join (select date(c.event_time) fdt,b.product_id product_id from tb_order_detail b left join tb_order_overall c using(order_id) left join tb_product_info d using(product_id) where d.shop_id = 901) f on datediff(a.dt,f.fdt) between 0 and 6 group by dt order by dt asc;