首页 > 试题广场 >

每个城市中评分最高的司机信息

[编程题]每个城市中评分最高的司机信息
  • 热度指数:59384 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解

用户打车记录表tb_get_car_record

id uid city event_time end_time order_id
1 101 北京 2021-10-01 07:00:00 2021-10-01 07:02:00
NULL
2 102 北京
2021-10-01 09:00:30
2021-10-01 09:01:00
9001
3 101 北京
2021-10-01 08:28:10
2021-10-01 08:30:00
9002
4 103 北京
2021-10-02 07:59:00
2021-10-02 08:01:00
9003
5 104 北京
2021-10-03 07:59:20
2021-10-03 08:01:00
9004
6 105 北京
2021-10-01 08:00:00
2021-10-01 08:02:10
9005
7 106 北京
2021-10-01 17:58:00
2021-10-01 18:01:00
9006
8 107 北京
2021-10-02 11:00:00
2021-10-02 11:01:00
9007
9 108 北京
2021-10-02 21:00:00
2021-10-02 21:01:00
9008
10 109 北京
2021-10-08 18:00:00
2021-10-08 18:01:00
9009
(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 9002 101 202 2021-10-01 08:30:00
NULL
2021-10-01 08:31:00
NULL
NULL
NULL
2 9001 102 202 2021-10-01 09:01:00
2021-10-01 09:06:00
2021-10-01 09:31:00
10 41.5 5
3 9003
103 202 2021-10-02 08:01:00
2021-10-02 08:15:00
2021-10-02 08:31:00
11 41.5 4
4 9004
104 202 2021-10-03 08:01:00
2021-10-03 08:13:00
2021-10-03 08:31:00
7.5 22 4
5 9005
105 203 2021-10-01 08:02:10
NULL
2021-10-01 08:31:00
NULL NULL NULL
6 9006
106 203 2021-10-01 18:01:00
2021-10-01 18:09:00
2021-10-01 18:31:00
8 25.5 5
7 9007
107 203 2021-10-02 11:01:00
2021-10-02 11:07:00
2021-10-02 11:31:00
9.9 30 5
8 9008
108 203 2021-10-02 21:01:00
2021-10-02 21:10:00
2021-10-02 21:31:00
13.2 38 4
9 9009 109 203 2021-10-08 18:01:00 2021-10-08 18:11:50
2021-10-08 18:51:00
13 40 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_time-接单时间end_time-打车结束时间)写入打车记录表;若一直无司机接单,超时或中途用户主动取消打车,则记录end_time-打车结束时间

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

  • 当司机接上乘客时,填充订单表中该start_time-开始计费的上车时间
  • 当订单完成时填充订单完成时间、里程数、费用;评分设为null,在用户给司机打1~5星评价后填充。

问题:请统计每个城市中评分最高的司机平均评分、日均接单量和日均行驶里程数。

:有多个司机评分并列最高时,都输出。
平均评分和日均接单量保留1位小数,
日均行驶里程数保留3位小数,按日均接单数升序排序。

2285068
示例数据的输出结果如下
city driver_id avg_grade avg_order_num avg_mileage
北京 203 4.8 1.7 14.700
解释:
示例数据中,在北京市,共有2个司机接单,202的平均评分为4.3,203的平均评分为4.8,因此北京的最高评分的司机为203;203的共在3天里接单过,一共接单5次(包含1次接单后未完成),因此日均接单数为1.7;总行驶里程数为44.1,因此日均行驶里程数为14.700
示例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
 (101, '北京', '2021-10-01 07:00:00', '2021-10-01 07:02:00', null),
 (102, '北京', '2021-10-01 09:00:30', '2021-10-01 09:01:00', 9001),
 (101, '北京', '2021-10-01 08:28:10', '2021-10-01 08:30:00', 9002),
 (103, '北京', '2021-10-02 07:59:00', '2021-10-02 08:01:00', 9003),
 (104, '北京', '2021-10-03 07:59:20', '2021-10-03 08:01:00', 9004),
 (105, '北京', '2021-10-01 08:00:00', '2021-10-01 08:02:10', 9005),
 (106, '北京', '2021-10-01 17:58:00', '2021-10-01 18:01:00', 9006),
 (107, '北京', '2021-10-02 11:00:00', '2021-10-02 11:01:00', 9007),
 (108, '北京', '2021-10-02 21:00:00', '2021-10-02 21:01:00', 9008),
 (109, '北京', '2021-10-08 18:00:00', '2021-10-08 18:01:00', 9009);

INSERT INTO tb_get_car_order(order_id, uid, driver_id, order_time, start_time, finish_time, mileage, fare, grade) VALUES
 (9002, 101, 202, '2021-10-01 08:30:00', null, '2021-10-01 08:31:00', null, null, null),
 (9001, 102, 202, '2021-10-01 09:01:00', '2021-10-01 09:06:00', '2021-10-01 09:31:00', 10.0, 41.5, 5),
 (9003, 103, 202, '2021-10-02 08:01:00', '2021-10-02 08:15:00', '2021-10-02 08:31:00', 11.0, 41.5, 4),
 (9004, 104, 202, '2021-10-03 08:01:00', '2021-10-03 08:13:00', '2021-10-03 08:31:00', 7.5, 22, 4),
 (9005, 105, 203, '2021-10-01 08:02:10', null, '2021-10-01 08:31:00', null, null, null),
 (9006, 106, 203, '2021-10-01 18:01:00', '2021-10-01 18:09:00', '2021-10-01 18:31:00', 8.0, 25.5, 5),
 (9007, 107, 203, '2021-10-02 11:01:00', '2021-10-02 11:07:00', '2021-10-02 11:31:00', 9.9, 30, 5),
 (9008, 108, 203, '2021-10-02 21:01:00', '2021-10-02 21:10:00', '2021-10-02 21:31:00', 13.2, 38, 4),
 (9009, 109, 203, '2021-10-08 18:01:00', '2021-10-08 18:11:50', '2021-10-08 18:51:00', 13, 40, 5);

输出

北京|203|4.8|1.7|14.700
with t as (select 
       a.city,
       b.driver_id,
       round(avg(b.grade),1) as avg_grade,
      round(count(b.order_id)/count(distinct date(b.order_time)),1) as avg_order_num,
       round(sum(b.mileage)/count(distinct date(b.order_time)),3) as avg_mileage
from tb_get_car_order as b
left join tb_get_car_record as a on a.order_id = b.order_id 
group by 1,2)


select city,driver_id,avg_grade ,avg_order_num,avg_mileage 
from (
select *,
      dense_rank() over (partition by city order by avg_grade desc ) as rn
from t) as c
where rn = 1
order by avg_order_num
看了解释以为求平均时是除以3天,看了别人的是除以count(distinct date(order_time))有接单的天数。如果中间有一天司机没接单,那这一天不要纳入分母。题目理解是关键,为什么题目很喜欢模棱两可,可能是觉得实际业务场景也经常模棱两可hhhhhh
发表于 2025-07-07 17:36:06 回复(0)
SELECT 
    city,
    o.driver_id,
    ROUND(AVG(grade),1) AS avg_grade,
    ROUND(COUNT(order_time) / COUNT(DISTINCT IF(start_time IS NULL, NULL, DATE(start_time))),1) AS avg_order_num,
    ROUND(SUM(IFNULL(mileage, 0)) / COUNT(DISTINCT IF(start_time IS NULL, NULL, DATE(start_time))),3) AS avg_mileage
FROM tb_get_car_order o 
JOIN tb_get_car_record r ON o.order_id = r.order_id
WHERE o.driver_id IN 
    (
    -- 评分排名第一的司机
    SELECT 
    driver_id
    FROM (
        SELECT 
            o.driver_id,
            r.city,
            AVG(grade) AS avg_grade,
            DENSE_RANK() OVER (PARTITION BY r.city ORDER BY AVG(grade) DESC) AS rk
        FROM tb_get_car_order o 
        JOIN tb_get_car_record r ON o.order_id = r.order_id
        WHERE grade IS NOT NULL
        GROUP BY r.city, o.driver_id
        ) a 
    WHERE rk = 1
    )
GROUP BY city, o.driver_id
ORDER BY avg_order_num ASC

为啥日均行程那里这么算偏大啊啊啊啊
发表于 2025-03-23 14:25:40 回复(1)
with
    t as (
        select
            t2.city city,
            t1.driver_id driver_id,
            round(avg(t1.grade), 1) avg_grade,
            round(
                count(t1.order_time) / count(distinct date (t1.order_time)),
                1
            ) avg_order_num,
            rank() over (
                partition by
                    t2.city
                order by
                    round(avg(t1.grade) ,1) desc
            ) rank_1,
            round(
                sum(t1.mileage) / count(distinct date (t1.order_time)),
                3
            ) avg_mileage
        from
            tb_get_car_order t1
            left join tb_get_car_record t2 on t1.order_id = t2.order_id
        group by
            t2.city,
            t1.driver_id
    )
select
    city,
    driver_id,
    avg_grade,
    avg_order_num,
    avg_mileage
from
    t
where
    rank_1 = 1
order by avg_order_num

发表于 2024-11-09 16:22:02 回复(0)
select
    city,
    driver_id,
    round(avg(grade), 1) avg_grade,
    round(
        count(a.order_id) / count(distinct date (order_time)),
        1
    ) avg_order_num,
    round(
        sum(mileage) / count(distinct date (order_time)),
        3
    ) avg_mileage
from
    tb_get_car_order a
    right join tb_get_car_record using (order_id)
where
    driver_id in (
        select
            driver_id
        from
            (
                select
                    driver_id,
                    dense_rank() over (
                        partition by
                            city
                        order by
                            ct desc
                    ) rn
                from
                    (
                        select
                            city,
                            driver_id,
                            round(avg(grade), 1) ct
                        from
                            tb_get_car_record a
                            right join tb_get_car_order b on a.order_id = b.order_id
                            and b.order_id is not null
                        group by
                            city,
                            driver_id
                    ) t
            ) t
        where
            rn = 1
    )
group by
    city,
    driver_id
order by
    avg_order_num

发表于 2024-10-09 13:46:51 回复(0)
第一个子查询,给出各个司机的数据
第二个查询,用窗口函数为这些司机的平均得分按city分组给排名
最外面,输出排名为1的数据
并列最高输出 通过dense_rank =1 来实现
SELECT
    city,
    driver_id,
    avg_grade,
    avg_order_num,
    avg_mileage
FROM(
    SELECT
        *,
        dense_rank() over(partition by city order by avg_grade desc) as t_rank
    FROM(    
        SELECT
            city,
            driver_id,
            ROUND(avg(grade),1) as avg_grade,
            ROUND(count(order_time)/count(distinct date(order_time)),1) as avg_order_num, 
            ROUND(SUM(mileage)/count(distinct date(order_time)),3) as avg_mileage 
        FROM
            tb_get_car_order
            JOIN tb_get_car_record using(order_id)
        GROUP BY
            city,driver_id
        ) temp
    ) city_rank
WHERE    t_rank=1
ORDER BY avg_order_num

发表于 2024-08-05 11:37:01 回复(0)
为什么这段代码提交会报错
select t2.city,t2.driver_id
,round(sum(grade)/count(grade),1)avg_grade
,round(count(*)/d_cnt,1) avg_order_num
,round(sum(mileage)/d_cnt,3) avg_mileage
from(
select *,
dense_rank() over(partition by city order by avg_gd desc) rk
from(
select city,driver_id,grade,mileage
,round(sum(grade) over(partition by driver_id)/count(grade) over(partition by driver_id),1) avg_gd
from tb_get_car_order
join tb_get_car_record using(order_id)
) t1 )t2
join (select driver_id,city,count(distinct date_format(start_time,'%Y-%m-%d')) d_cnt from tb_get_car_order
join tb_get_car_record using(order_id) 
group by city,driver_id) t3 on t3.driver_id=t2.driver_id and t3.city=t2.city
where rk=1
group by 1,2
order by 3


发表于 2024-06-05 17:50:55 回复(0)
select t1.city, t1.driver_id, t1.avg_grade,
round(t1.order_num/count(distinct day(t2.order_time)),1) as avg_order_num,
round(t1.sum_mileage/count(distinct day(t2.order_time)),3) as avg_mileage
from
(select city, driver_id, r1.avg_grade, r1.order_num, 
r1.sum_mileage 
from
(select city, driver_id, round(avg(grade),1) as avg_grade, 
count(*) as order_num, sum(mileage) as sum_mileage, rank() over(partition by city order by avg(grade) desc) as rk
from tb_get_car_order, tb_get_car_record
where tb_get_car_order.order_id=tb_get_car_record.order_id
group by driver_id, city)r1
where rk=1
)t1 join tb_get_car_order t2
on t1.driver_id=t2.driver_id
group by t1.city, t1.driver_id, t1.avg_grade
order by avg_order_num

发表于 2024-06-04 17:31:35 回复(0)
SELECT d.city,d.driver_id,
ROUND(AVG(t.grade),1)'avg_grade',
ROUND(COUNT(*)/COUNT(DISTINCT DATE(t.order_time)),1)'avg_order_num',
ROUND(SUM(t.mileage)/COUNT(DISTINCT DATE(t.order_time)),3)'avg_mileage'
FROM(SELECT city,driver_id
FROM(SELECT t1.city,t2.driver_id,ROUND(AVG(t2.grade),1)'avg',
RANK()OVER(PARTITION BY city ORDER BY AVG(t2.grade) DESC)'rk'
FROM tb_get_car_record t1
INNER JOIN tb_get_car_order t2 ON t1.order_id = t2.order_id
GROUP BY t1.city,t2.driver_id)p
WHERE rk = 1)d
INNER JOIN tb_get_car_order t ON d.driver_id = t.driver_id
GROUP BY d.city,d.driver_id
ORDER BY avg_order_num
编辑于 2024-04-25 10:47:55 回复(0)
一种不用窗口函数的方法
with t1 as (select city, driver_id, round(avg(grade), 1) as avg_grade, round(count(order_time) / count(distinct date(order_time)), 1) as avg_order_num,
round(sum(mileage) / count(distinct date(order_time)), 3) as avg_mileage
from tb_get_car_order as d inner join tb_get_car_record as u using(order_id)
group by city, driver_id)

select * 
from t1
group by city, driver_id
having avg_grade in (select max(avg_grade) from t1 group by city)
order by avg_order_num

编辑于 2024-04-07 17:54:49 回复(0)
with 
t as (  #总表
select city, order_time, driver_id as did, mileage, grade
from tb_get_car_record join tb_get_car_order using(order_id)
),
t1 as (  #司机平均分表
select city, did, avg(grade) as avg from t
group by city, did
), 
t2 as ( #由t1得到每个城市最高分
select city, max(avg) as max from t1
group by city
),
t3 as ( #由t1和t2得到最高评分司机
select did, avg from t1 inner join t2 using(city)
where avg=max 
),
t4 as ( #司机的日均接单和里程数
select did, 
    count(order_time)/count(distinct date(order_time)) as avg_n,
    sum(mileage)/count(distinct date(order_time)) as avg_m
from t
group by did
)

select city, did, round(avg(avg), 1), 
    round(avg(avg_n), 1), round(avg(avg_m), 3) 
from t3 
    inner join t using(did) 
    inner join t4 using(did)
group by city, did
order by round(avg(avg_n), 1);

编辑于 2024-02-12 22:08:09 回复(0)
WITH t1 AS (
SELECT driver_id,ROUND(AVG(grade),1) avg_grade,city FROM  tb_get_car_order tbo JOIN tb_get_car_record tbr USING(order_id) GROUP BY driver_id,city
)
#再根据每个城市的最高评分定位到司机id,然后根据司机id计算其他值
SELECT city,driver_id,ROUND(AVG(grade),1) avg_grade,
ROUND(COUNT(order_id)/COUNT(DISTINCT DATE(order_time)),1) avg_order_num,
ROUND(SUM(mileage)/COUNT(DISTINCT DATE(order_time)),3) avg_mileage
FROM tb_get_car_order tbo JOIN tb_get_car_record tbr USING(order_id) GROUP BY city,driver_id HAVING (city,avg_grade) IN (
SELECT city,MAX(avg_grade) avg_grade FROM t1 group by city
) ORDER BY avg_order_num;
这里需要注意,聚合函数如果用了分组,前面不能出现未聚合的列名
编辑于 2023-12-23 22:51:07 回复(0)
with 
    tmp as (
        select city
            ,driver_id
            ,round(avg(grade),1) avg_grade
            ,round(count(order_time)/count(distinct date(order_time)),1) avg_order_num
            ,round(sum(mileage)/count(distinct date(order_time)),3) avg_mileage
        from tb_get_car_record 
        join tb_get_car_order
        using(order_id)
        group by city
            ,driver_id
    )
select *
from tmp
where avg_grade in (
    select max(avg_grade)
    from tmp
    group by city
)
order by avg_order_num

发表于 2023-11-28 10:18:56 回复(0)
select city,driver_id,round(avg_grade,1) avg_grade,round(avg_order_num,1) avg_order_num,round(avg_mileage,3) avg_mileage from(
    select *, dense_rank() over(partition by city order by avg_grade desc) as r from
    (select city,driver_id,avg(grade) as avg_grade, count(order_time)/count(distinct date(order_time)) as avg_order_num, sum(mileage)/count(distinct date(order_time)) as avg_mileage 
    from tb_get_car_record u inner join tb_get_car_order d on u.order_id=d.order_id group by city,driver_id)c)cc
    where r=1 order by avg_order_num; 

发表于 2023-08-25 15:20:31 回复(0)