列表

详情


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
(uid 用户ID, city-城市, event_time-打车时间, end_time-打车结束时间, order_id-订单号)

打车订单表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-订单号, uid-用户ID, driver_id-司机ID, order_time-接单时间, start_time-开始计费的上车时间, finish_time-订单完成时间, mileage-行驶里程数, fare-费用, grade-评分)

场景逻辑说明

  • 用户提交打车请求后,在用户打车记录表生成一条打车记录,订单号-order_id设为null

  • 当有司机接单时,在打车订单表生成一条订单,填充接单时间-order_time 及其左边的字段,上车时间-start_time及其右边的字段全部为null,并把订单号-order_id接单时间-order_timeend_time-打车结束时间)写入打车记录表;若一直无司机接单,超时或中途用户主动取消打车,则记录打车结束时间-end_time

  • 若乘客上车前,乘客或司机点击取消订单,会将打车订单表对应订单的finish_time-订单完成时间填充为取消时间,其余字段设为null

  • 当司机接上乘客时,填充订单表中该订单的start_time-上车时间

  • 当订单完成时填充订单完成时间、里程数、费用;评分设为null,在用户给司机打1~5星评价后填充。


问题统计周一到周五各时段的叫车量、平均等待接单时间和平均调度时间。全部以event_time-开始打车时间为时段划分依据,平均等待接单时间和平均调度时间均保留1位小数,平均调度时间仅计算完成了的订单,结果按叫车量升序排序。

  • 不同时段定义:早高峰 [07:00:00 , 09:00:00)、工作时间 [09:00:00 , 17:00:00)、晚高峰 [17:00:00 , 20:00:00)、休息时间 [20:00:00 , 07:00:00
  • 时间区间左闭右开(即7:00:00算作早高峰,而9:00:00不算做早高峰)
  • 从开始打车到司机接单为等待接单时间,从司机接单到上车为调度时间。
输出示例
示例数据的输出结果如下:
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

上一题