SQL178. 工作日各时段叫车量、等待接单时间和调度时间
描述
用户打车记录表tb_get_car_record
id | uid | city | event_time | end_time | order_id |
1 | 107 | 北京 | 2021-09-20 11:00:00 | 2021-09-20 11:00:30 | 9017 |
2 | 108 | 北京 | 2021-09-20 21:00:00 | 2021-09-20 21:00:40 | 9008 |
3 | 108 | 北京 | 2021-09-20 18:59:30 | 2021-09-20 19:01:00 | 9018 |
4 | 102 | 北京 | 2021-09-21 08:59:00 | 2021-09-21 09:01:00 | 9002 |
5 | 106 | 北京 | 2021-09-21 17:58:00 | 2021-09-21 18:01:00 | 9006 |
6 | 103 | 北京 | 2021-09-22 07:58:00 | 2021-09-22 08:01:00 | 9003 |
7 | 104 | 北京 | 2021-09-23 07:59:00 | 2021-09-23 08:01:00 | 9004 |
8 | 103 | 北京 | 2021-09-24 19:59:20 | 2021-09-24 20:01:00 | 9019 |
9 | 101 | 北京 | 2021-09-24 08:28:10 | 2021-09-24 08:30:00 | 9011 |
打车订单表tb_get_car_order
id | order_id | uid | driver_id | order_time | start_time | finish_time | mileage | fare | grade |
1 | 9017 | 107 | 213 | 2021-09-20 11:00:30 | 2021-09-20 11:02:10 | 2021-09-20 11:31:00 | 11 | 38 | 5 |
2 | 9008 | 108 | 204 | 2021-09-20 21:00:40 | 2021-09-20 21:03:00 | 2021-09-20 21:31:00 | 13.2 | 38 | 4 |
3 | 9018 | 108 | 214 | 2021-09-20 19:01:00 | 2021-09-20 19:04:50 | 2021-09-20 19:21:00 | 14 | 38 | 5 |
4 | 9002 | 102 | 202 | 2021-09-21 09:01:00 | 2021-09-21 09:06:00 | 2021-09-21 09:31:00 | 10 | 41.5 | 5 |
5 | 9006 | 106 | 203 | 2021-09-21 18:01:00 | 2021-09-21 18:09:00 | 2021-09-21 18:31:00 | 8 | 25.5 | 4 |
6 | 9007 | 107 | 203 | 2021-09-22 11:01:00 | 2021-09-22 11:07:00 | 2021-09-22 11:31:00 | 9.9 | 30 | 5 |
7 | 9003 | 103 | 202 | 2021-09-22 08:01:00 | 2021-10-22 08:15:00 | 2021-10-22 08:31:00 | 11 | 41.5 | 4 |
8 | 9004 | 104 | 202 | 2021-09-23 08:01:00 | 2021-09-23 08:13:00 | 2021-09-23 08:31:00 | 7.5 | 22 | 4 |
9 | 9005 | 105 | 202 | 2021-09-23 10:01:00 | 2021-09-23 10:13:00 | 2021-09-23 10:31:00 | 9 | 29 | 5 |
10 | 9019 | 103 | 202 | 2021-09-24 20:01:00 | 2021-09-24 20:11:00 | 2021-09-24 20:51:00 | 10 | 39 | 4 |
11 | 9011 | 101 | 211 | 2021-09-24 08:30:00 | 2021-09-24 08:31:00 | 2021-09-24 08:54:00 | 10 | 35 | 5 |
场景逻辑说明:
用户提交打车请求后,在用户打车记录表生成一条打车记录,订单号-order_id设为null;
当有司机接单时,在打车订单表生成一条订单,填充接单时间-order_time 及其左边的字段,上车时间-start_time及其右边的字段全部为null,并把订单号-order_id和接单时间-order_time(end_time-打车结束时间)写入打车记录表;若一直无司机接单,超时或中途用户主动取消打车,则记录打车结束时间-end_time。
若乘客上车前,乘客或司机点击取消订单,会将打车订单表对应订单的finish_time-订单完成时间填充为取消时间,其余字段设为null。
当司机接上乘客时,填充订单表中该订单的start_time-上车时间。
当订单完成时填充订单完成时间、里程数、费用;评分设为null,在用户给司机打1~5星评价后填充。
period | get_car_num | avg_wait_time | avg_dispatch_time |
工作时间 | 1 | 0.5 | 1.7 |
休息时间 | 1 | 0.7 | 2.3 |
晚高峰 | 3 | 2.1 | 7.3 |
早高峰 | 4 | 2.2 | 8.0 |
解释:订单9017打车开始于11点整,属于工作时间,等待时间30秒,调度时间为1分40秒,示例数据中工作时间打车订单就一个,平均等待时间0.5分钟,平均调度时间1.7分钟。
示例1
输入:
DROP TABLE IF EXISTS tb_get_car_record,tb_get_car_order; CREATE TABLE tb_get_car_record ( id INT PRIMARY KEY AUTO_INCREMENT COMMENT '自增ID', uid INT NOT NULL COMMENT '用户ID', city VARCHAR(10) NOT NULL COMMENT '城市', event_time datetime COMMENT '打车时间', end_time datetime COMMENT '打车结束时间', order_id INT COMMENT '订单号' ) CHARACTER SET utf8 COLLATE utf8_bin; CREATE TABLE tb_get_car_order ( id INT PRIMARY KEY AUTO_INCREMENT COMMENT '自增ID', order_id INT NOT NULL COMMENT '订单号', uid INT NOT NULL COMMENT '用户ID', driver_id INT NOT NULL COMMENT '司机ID', order_time datetime COMMENT '接单时间', start_time datetime COMMENT '开始计费的上车时间', finish_time datetime COMMENT '订单结束时间', mileage FLOAT COMMENT '行驶里程数', fare FLOAT COMMENT '费用', grade TINYINT COMMENT '评分' ) CHARACTER SET utf8 COLLATE utf8_bin; INSERT INTO tb_get_car_record(uid, city, event_time, end_time, order_id) VALUES (107, '北京', '2021-09-20 11:00:00', '2021-09-20 11:00:30', 9017), (108, '北京', '2021-09-20 21:00:00', '2021-09-20 21:00:40', 9008), (108, '北京', '2021-09-20 18:59:30', '2021-09-20 19:01:00', 9018), (102, '北京', '2021-09-21 08:59:00', '2021-09-21 09:01:00', 9002), (106, '北京', '2021-09-21 17:58:00', '2021-09-21 18:01:00', 9006), (103, '北京', '2021-09-22 07:58:00', '2021-09-22 08:01:00', 9003), (104, '北京', '2021-09-23 07:59:00', '2021-09-23 08:01:00', 9004), (103, '北京', '2021-09-24 19:59:20', '2021-09-24 20:01:00', 9019), (101, '北京', '2021-09-24 08:28:10', '2021-09-24 08:30:00', 9011); INSERT INTO tb_get_car_order(order_id, uid, driver_id, order_time, start_time, finish_time, mileage, fare, grade) VALUES (9017, 107, 213, '2021-09-20 11:00:30', '2021-09-20 11:02:10', '2021-09-20 11:31:00', 11, 38, 5), (9008, 108, 204, '2021-09-20 21:00:40', '2021-09-20 21:03:00', '2021-09-20 21:31:00', 13.2, 38, 4), (9018, 108, 214, '2021-09-20 19:01:00', '2021-09-20 19:04:50', '2021-09-20 19:21:00', 14, 38, 5), (9002, 102, 202, '2021-09-21 09:01:00', '2021-09-21 09:06:00', '2021-09-21 09:31:00', 10.0, 41.5, 5), (9006, 106, 203, '2021-09-21 18:01:00', '2021-09-21 18:09:00', '2021-09-21 18:31:00', 8.0, 25.5, 4), (9007, 107, 203, '2021-09-22 11:01:00', '2021-09-22 11:07:00', '2021-09-22 11:31:00', 9.9, 30, 5), (9003, 103, 202, '2021-09-22 08:01:00', '2021-09-22 08:15:00', '2021-09-22 08:31:00', 11.0, 41.5, 4), (9004, 104, 202, '2021-09-23 08:01:00', '2021-09-23 08:13:00', '2021-09-23 08:31:00', 7.5, 22, 4), (9005, 105, 202, '2021-09-23 10:01:00', '2021-09-23 10:13:00', '2021-09-23 10:31:00', 9, 29, 5), (9019, 103, 202, '2021-09-24 20:01:00', '2021-09-24 20:11:00', '2021-09-24 20:51:00', 10, 39, 4), (9011, 101, 211, '2021-09-24 08:30:00', '2021-09-24 08:31:00', '2021-09-24 08:54:00', 10, 35, 5);
输出:
工作时间|1|0.5|1.7 休息时间|1|0.7|2.3 晚高峰|3|2.1|7.3 早高峰|4|2.2|8.0
Mysql 解法, 执行用时: 36ms, 内存消耗: 6500KB, 提交时间: 2022-01-27
select (case when time(event_time) >= '07:00:00' and time(event_time) < '09:00:00' then '早高峰' when time(event_time) >= '09:00:00' and time(event_time) < '17:00:00' then '工作时间' when time(event_time) >= '17:00:00' and time(event_time) < '20:00:00' then '晚高峰' else '休息时间' end) as period, count(tgcr.order_id) as get_car_num, round(avg(timestampdiff(second,event_time,order_time)/60),1) as avg_wait_time, round(avg(timestampdiff(second,order_time,start_time)/60),1) as avg_dispatch_time from tb_get_car_record as tgcr join tb_get_car_order tgco on tgcr.order_id = tgco.order_id where weekday(event_time) between 0 and 4 group by period order by get_car_num
Mysql 解法, 执行用时: 36ms, 内存消耗: 6512KB, 提交时间: 2022-01-23
select case when hour(event_time) in (7,8) then '早高峰' when hour(event_time) between 9 and 16 then '工作时间' when hour(event_time) between 17 and 19 then '晚高峰' else '休息时间' end as period, count(event_time) as get_car_num, round(avg(wait_time)/60,1) as avg_wait_time, round(avg(dispatch_time)/60,1) as avg_dispatch_time from (select event_time, timestampdiff(second,event_time, order_time) as wait_time, timestampdiff(second,order_time, start_time) as dispatch_time from tb_get_car_order tb1 inner join tb_get_car_record tb2 on tb1.order_id=tb2.order_id where weekday(event_time) between 0 and 4) t1 group by period order by get_car_num
Mysql 解法, 执行用时: 37ms, 内存消耗: 6400KB, 提交时间: 2022-01-22
select case when hour(dt) in (7,8) then '早高峰' when hour(dt) between 9 and 16 then '工作时间' when hour(dt) between 17 and 19 then '晚高峰' else '休息时间' end as period, count(order_id) as get_car_num, round(avg(wait_time),1) as avg_wait_time, round(avg(dispatch_time),1) as avg_dispatch_time from (select order_id, date_format(event_time, '%T') dt, round(TIMESTAMPDIFF(second, event_time , end_time)/60,1) AS wait_time from tb_get_car_record where WEEKDAY(event_time) BETWEEN 0 and 4 ) as wait_t join (select order_id, round(TIMESTAMPDIFF(second, order_time , start_time)/60,1) AS dispatch_time from tb_get_car_order where WEEKDAY(order_time) BETWEEN 0 and 4 ) as dispatch_t using(order_id) group by period order by get_car_num
Mysql 解法, 执行用时: 37ms, 内存消耗: 6400KB, 提交时间: 2022-01-03
SELECT period, COUNT(event_time) order_num, ROUND(AVG(wait_time), 1), ROUND(SUM(dispatch_time)/COUNT(dispatch_time), 1) FROM( SELECT event_time, CASE WHEN RIGHT(event_time, 8) >='07:00:00' AND RIGHT(event_time, 8) < '09:00:00' THEN '早高峰' WHEN RIGHT(event_time, 8) >='09:00:00' AND RIGHT(event_time, 8) < '17:00:00' THEN '工作时间' WHEN RIGHT(event_time, 8) >='17:00:00' AND RIGHT(event_time, 8) < '20:00:00' THEN '晚高峰' ELSE '休息时间' END period, TIMESTAMPDIFF(SECOND, event_time, end_time)/60 wait_time, TIMESTAMPDIFF(SECOND, order_time, start_time)/60 dispatch_time FROM tb_get_car_record tgcr LEFT JOIN tb_get_car_order USING(order_id) WHERE DATE_FORMAT(event_time, '%w') BETWEEN 1 AND 5 ) a GROUP BY period ORDER BY order_num
Mysql 解法, 执行用时: 37ms, 内存消耗: 6424KB, 提交时间: 2021-12-07
select case when subString_index(event_time, ' ', -1) between '07:00:00' and '08:59:59' then '早高峰' when subString_index(event_time, ' ', -1) between '09:00:00' and '16:59:59' then '工作时间' when subString_index(event_time, ' ', -1) between '17:00:00' and '19:59:59' then '晚高峰' else '休息时间' end period, count(1) AS get_car_num, round( avg(TIMESTAMPdiff(second, event_time, order_time))/60, 1 ) AS avg_wait_time, round( avg(Timestampdiff(second, order_time, start_time))/60, 1 ) AS avg_dispatch_time from tb_get_car_record a JOIN tb_get_car_order b ON a.order_id = b.order_id WHERE WEEKDAY(order_time) NOT IN(5, 6) GROUP BY period ORDER BY get_car_num