SQL179. 各城市最大同时等车人数
描述
id | uid | city | event_time | end_time | order_id |
1 | 108 | 北京 | 2021-10-20 08:00:00 | 2021-10-20 08:00:40 | 9008 |
2 | 118 | 北京 | 2021-10-20 08:00:10 | 2021-10-20 08:00:45 | 9018 |
3 | 102 | 北京 | 2021-10-20 08:00:30 | 2021-10-20 08:00:50 | 9002 |
4 | 106 | 北京 | 2021-10-20 08:05:41 | 2021-10-20 08:06:00 | 9006 |
5 | 103 | 北京 | 2021-10-20 08:05:50 | 2021-10-20 08:07:10 | 9003 |
6 | 104 | 北京 | 2021-10-20 08:01:01 | 2021-10-20 08:01:20 | 9004 |
7 | 105 | 北京 | 2021-10-20 08:01:15 | 2021-10-20 08:01:30 | 9019 |
8 | 101 | 北京 | 2021-10-20 08:28:10 | 2021-10-20 08:30:00 | 9011 |
id | order_id | uid | driver_id | order_time | start_time | finish_time | mileage | fare | grade |
1 | 9008 | 108 | 204 | 2021-10-20 08:00:40 | 2021-10-20 08:03:00 | 2021-10-20 08:31:00 | 13.2 | 38 | 4 |
2 | 9018 | 108 | 214 | 2021-10-20 08:00:45 | 2021-10-20 08:04:50 | 2021-10-20 08:21:00 | 14 | 38 | 5 |
3 | 9002 | 102 | 202 | 2021-10-20 08:00:50 | 2021-10-20 08:06:00 | 2021-10-20 08:31:00 | 10 | 41.5 | 5 |
4 | 9006 | 106 | 206 | 2021-10-20 08:06:00 | 2021-10-20 08:09:00 | 2021-10-20 08:31:00 | 8 | 25.5 | 4 |
5 | 9003 | 103 | 203 | 2021-10-20 08:07:10 | 2021-10-20 08:15:00 | 2021-10-20 08:31:00 | 11 | 41.5 | 4 |
6 | 9004 | 104 | 204 | 2021-10-20 08:01:20 | 2021-10-20 08:13:00 | 2021-10-20 08:31:00 | 7.5 | 22 | 4 |
7 | 9019 | 105 | 205 | 2021-10-20 08:01:30 | 2021-10-20 08:11:00 | 2021-10-20 08:51:00 | 10 | 39 | 4 |
8 | 9011 | 101 | 211 | 2021-10-20 08:30:00 | 2021-10-20 08:31:00 | 2021-10-20 08:54:00 | 10 | 35 | 5 |
场景逻辑说明:
用户提交打车请求后,在用户打车记录表生成一条打车记录,订单号-order_id设为null;
当有司机接单时,在打车订单表生成一条订单,填充接单时间-order_time及其左边的字段,上车时间及其右边的字段全部为null,并把订单号和接单时间(打车结束时间)写入打车记录表;若一直无司机接单、超时或中途用户主动取消打车,则记录打车结束时间。
若乘客上车前,乘客或司机点击取消订单,会将打车订单表对应订单的订单完成时间-finish_time填充为取消时间,其余字段设为null。
当司机接上乘客时,填充打车订单表中该订单的上车时间start_time。
city | max_wait_uv |
北京 | 5 |
示例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 (108, '北京', '2021-10-20 08:00:00', '2021-10-20 08:00:40', 9008), (108, '北京', '2021-10-20 08:00:10', '2021-10-20 08:00:45', 9018), (102, '北京', '2021-10-20 08:00:30', '2021-10-20 08:00:50', 9002), (106, '北京', '2021-10-20 08:05:41', '2021-10-20 08:06:00', 9006), (103, '北京', '2021-10-20 08:05:50', '2021-10-20 08:07:10', 9003), (104, '北京', '2021-10-20 08:01:01', '2021-10-20 08:01:20', 9004), (103, '北京', '2021-10-20 08:01:15', '2021-10-20 08:01:30', 9019), (101, '北京', '2021-10-20 08:28:10', '2021-10-20 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 (9008, 108, 204, '2021-10-20 08:00:40', '2021-10-20 08:03:00', '2021-10-20 08:31:00', 13.2, 38, 4), (9018, 108, 214, '2021-10-20 08:00:45', '2021-10-20 08:04:50', '2021-10-20 08:21:00', 14, 38, 5), (9002, 102, 202, '2021-10-20 08:00:50', '2021-10-20 08:06:00', '2021-10-20 08:31:00', 10.0, 41.5, 5), (9006, 106, 203, '2021-10-20 08:06:00', '2021-10-20 08:09:00', '2021-10-20 08:31:00', 8.0, 25.5, 4), (9003, 103, 202, '2021-10-20 08:07:10', '2021-10-20 08:15:00', '2021-10-20 08:31:00', 11.0, 41.5, 4), (9004, 104, 202, '2021-10-20 08:01:20', '2021-10-20 08:13:00', '2021-10-20 08:31:00', 7.5, 22, 4), (9019, 103, 202, '2021-10-20 08:01:30', '2021-10-20 08:11:00', '2021-10-20 08:51:00', 10, 39, 4), (9011, 101, 211, '2021-10-20 08:30:00', '2021-10-20 08:31:00', '2021-10-20 08:54:00', 10, 35, 5);
输出:
北京|5
Mysql 解法, 执行用时: 36ms, 内存消耗: 6396KB, 提交时间: 2022-01-26
with t1 as( SELECT city,date(event_time) as dt,r.uid,event_time as time,1 as tag from tb_get_car_record r left join tb_get_car_order using(order_id) where date_format(event_time,'%Y-%m')='2021-10' union SELECT city,date(event_time) as dt,r.uid,if(end_time=order_time,start_time,end_time)as time,-1 as tag from tb_get_car_record r left join tb_get_car_order using(order_id) where date_format(event_time,'%Y-%m')='2021-10'), t2 as( SELECT *,sum(tag) over(PARTITION by city,dt order by time asc,tag desc) as wait_num from t1) SELECT city,max(wait_num) as max_wait_num from t2 GROUP BY city,dt ORDER BY 2,1
Mysql 解法, 执行用时: 36ms, 内存消耗: 6508KB, 提交时间: 2021-12-08
select city, max(cnt) max_wait_uv from (select city, wait_time, sum(num)over(partition by city order by wait_time asc,num desc) cnt from (select city, event_time wait_time, 1 num from tb_get_car_record where date(event_time) between '2021-10-01' and '2021-10-31' union all select b.city, coalesce(a.start_time,a.finish_time) wait_time, -1 num from tb_get_car_order a left join tb_get_car_record b on a.order_id = b.order_id where date(coalesce(a.start_time,a.finish_time)) between '2021-10-01' and '2021-10-31') m )n group by city order by max_wait_uv, city
Mysql 解法, 执行用时: 37ms, 内存消耗: 6392KB, 提交时间: 2022-01-03
SELECT city, MAX(sum_wait_num) FROM( SELECT city, time, SUM(if_wait) OVER(PARTITION BY city, left(time, 10) ORDER BY time, if_wait DESC) sum_wait_num FROM( SELECT city, event_time time, 1 if_wait FROM tb_get_car_record UNION ALL SELECT city, IFNULL(start_time, finish_time) time, -1 if_wait FROM tb_get_car_order JOIN tb_get_car_record USING(order_id) )a )b WHERE LEFT(time, 7) = '2021-10' GROUP BY city ORDER BY MAX(sum_wait_num), city
Mysql 解法, 执行用时: 37ms, 内存消耗: 6400KB, 提交时间: 2021-12-08
WITH tmp AS( SELECT city, event_time dt, 1 diff #开始等待,人数+1 FROM tb_get_car_record WHERE LEFT(event_time, 7) = '2021-10' UNION all SELECT city, o.start_time dt, -1 diff #顺利上车,人数-1 FROM tb_get_car_record r LEFT JOIN tb_get_car_order o USING(order_id) WHERE LEFT(o.start_time, 7) = '2021-10' AND start_time IS NOT NULL UNION all SELECT city, o.finish_time dt, -1 diff #上车前取消,人数-1 FROM tb_get_car_record r LEFT JOIN tb_get_car_order o USING(order_id) WHERE LEFT(o.finish_time, 7) = '2021-10' AND start_time IS NULL ) select city, max(wait_uv) as max_wait_uv from (SELECT city, sum(diff) over(partition by city,date(dt) order by dt,diff desc) as wait_uv from tmp)a GROUP BY city order by max_wait_uv,city
Mysql 解法, 执行用时: 37ms, 内存消耗: 6408KB, 提交时间: 2022-01-22
SELECT city, MAX(wait_uv) as max_wait_uv FROM ( SELECT city, t , SUM(num_change) OVER (PARTITION BY city ORDER BY t, num_change DESC) as wait_uv FROM ( SELECT city, event_time as t, 1 AS num_change FROM tb_get_car_record WHERE DATE_FORMAT(event_time, '%Y%m') = '202110' UNION ALL SELECT city, IFNULL(start_time, IFNULL(finish_time, order_time)) as t, -1 AS num_change FROM tb_get_car_record JOIN tb_get_car_order USING (order_id) WHERE DATE_FORMAT(event_time, '%Y%m') = '202110' ) time_num_changes ) num_waiting GROUP BY 1 ORDER BY 2, 1