列表

详情


SQL179. 各城市最大同时等车人数

描述

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


场景逻辑说明

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

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

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

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

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

问题:请统计各个城市在2021年10月期间,单日中最大的同时等车人数。

:   等车指从开始打车起,直到取消打车、取消等待或上车前的这段时间里用户的状态。
如果同一时刻有人停止等车,有人开始等车,等车人数记作先增加后减少。
结果按各城市最大等车人数升序排序,相同时按城市升序排序。

输出示例
示例结果如下
city max_wait_uv
北京 5
解释:由打车订单表可以得知北京2021年10月20日有8条打车记录,108号乘客从08:00:00等到08:03:00,118号乘客从08:00:10等到08:04:50....,由此得知08:02:00秒时刻,共有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

上一题