题解 | #工作日各时段叫车量、等待接单时间和调度时间#

工作日各时段叫车量、等待接单时间和调度时间

https://www.nowcoder.com/practice/34f88f6d6dc549f6bc732eb2128aa338

题目

  • 统计周一到周五各时段的叫车量、平均等待接单时间和平均调度时间
  • 全部以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不算做早高峰)
  • 等待接单时间:从开始打车到司机接单为等待接单时间,即 end_time - event_time
  • 调度时间:从司机接单到上车为调度时间,即 start_time - order_time

日期函数 —— 用于提取周几(参考链接:MYSQL经典SQL之星期问题 ):

  • WEEKDAY() :取值为0~6,对应星期一到星期日,每周以星期一为第一天;如,0即代表星期一
  • DAYOFWEEK() : 取值为1~7,对应星期日到星期六,每周以星期日为第一天;如,2即代表星期一
  • DAYNAME() : 取值为Sunday~Saturday,对应星期日到星期六,第一天是星期日;该函数与参数lc_time_names有关,如果设置此参数值为"zh_CN",则得到对应的中文名称“星期日”~“星期六”

解题步骤:

步骤 1:针对周一到周五的打车记录,根据event_time来拆分叫车的时间段

  • 周一到周五的识别,需要使用WEEKDAY()函数来识别和筛选
  • 拆分不同时段则需要使用CASE WHEN和TIME函数
    SELECT CASE WHEN TIME(cr.event_time) >= "07:00:00" AND TIME(cr.event_time) < "09:00:00" THEN "早高峰"
                WHEN TIME(cr.event_time) >= "09:00:00" AND TIME(cr.event_time) < "17:00:00" THEN "工作时间"
                WHEN TIME(cr.event_time) >= "17:00:00" AND TIME(cr.event_time) < "20:00:00" THEN "晚高峰"
                WHEN TIME(cr.event_time) >= "20:00:00" OR TIME(cr.event_time) < "07:00:00" THEN "休息时间" 
                ELSE NULL END AS period
    FROM tb_get_car_order AS co LEFT OUTER JOIN tb_get_car_record AS cr
    ON co.order_id = cr.order_id
    /* 需要先把event_time的具体日期提取出来,再使用WEEKDAY来识别其周几,0-4代表周一到五 */
    WHERE WEEKDAY(DATE(cr.event_time)) BETWEEN 0 AND 4

步骤 2:计算每一次打车记录的等待时间和调度时间,注意:一定要先以秒为单位计算时间差

SELECT
       CASE WHEN TIME(cr.event_time) >= "07:00:00" AND TIME(cr.event_time) < "09:00:00" THEN "早高峰"
            WHEN TIME(cr.event_time) >= "09:00:00" AND TIME(cr.event_time) < "17:00:00" THEN "工作时间"
            WHEN TIME(cr.event_time) >= "17:00:00" AND TIME(cr.event_time) < "20:00:00" THEN "晚高峰"
            WHEN TIME(cr.event_time) >= "20:00:00" OR TIME(cr.event_time) < "07:00:00" THEN "休息时间" 
            ELSE NULL END AS period,
        /* 使用TIMESTAMPDIFF还计算时间差 */
        TIMESTAMPDIFF(SECOND, cr.event_time, cr.end_time) AS wait_time,
        TIMESTAMPDIFF(SECOND, co.order_time, co.start_time) AS dispatch_time
FROM tb_get_car_order AS co LEFT OUTER JOIN tb_get_car_record AS cr
ON co.order_id = cr.order_id
/* 需要先把event_time的具体日期提取出来,再使用WEEKDAY来识别其周几,0-4代表周一到五 */
WHERE WEEKDAY(DATE(cr.event_time)) BETWEEN 0 AND 4

步骤 3:根据时间段进行GROUP BY分组,并计算各时段的叫车量、平均等待接单时间和平均调度时间

  • 注意,在计算平均时间差的时候,还需要将“秒”转化为“分钟”,即,除以60,之后再保留1位小数
    SELECT
         CASE WHEN TIME(cr.event_time) >= "07:00:00" AND TIME(cr.event_time) < "09:00:00" THEN "早高峰"
              WHEN TIME(cr.event_time) >= "09:00:00" AND TIME(cr.event_time) < "17:00:00" THEN "工作时间"
              WHEN TIME(cr.event_time) >= "17:00:00" AND TIME(cr.event_time) < "20:00:00" THEN "晚高峰"
              WHEN TIME(cr.event_time) >= "20:00:00" OR TIME(cr.event_time) < "07:00:00" THEN "休息时间" 
              ELSE NULL END AS period,
          /* 计算叫车量 */
          COUNT(co.order_id) AS get_car_num,
          /* 使用TIMESTAMPDIFF还计算时间差 */ 
          ROUND(AVG(TIMESTAMPDIFF(SECOND, cr.event_time, cr.end_time)) / 60, 1) AS avg_wait_time,
          ROUND(AVG(TIMESTAMPDIFF(SECOND, co.order_time, co.start_time)) / 60, 1) AS avg_dispatch_time
    FROM tb_get_car_order AS co LEFT OUTER JOIN tb_get_car_record AS cr
    ON co.order_id = cr.order_id
    WHERE WEEKDAY(DATE(cr.event_time)) BETWEEN 0 AND 4
    GROUP BY CASE WHEN TIME(cr.event_time) >= "07:00:00" AND TIME(cr.event_time) < "09:00:00" THEN "早高峰"
                WHEN TIME(cr.event_time) >= "09:00:00" AND TIME(cr.event_time) < "17:00:00" THEN "工作时间"
                WHEN TIME(cr.event_time) >= "17:00:00" AND TIME(cr.event_time) < "20:00:00" THEN "晚高峰"
                WHEN TIME(cr.event_time) >= "20:00:00" OR TIME(cr.event_time) < "07:00:00" THEN "休息时间" 
                ELSE NULL END
    /* 根据叫车量升序排列 */
    ORDER BY get_car_num ASC;
全部评论

相关推荐

点赞 1 评论
分享
牛客网
牛客企业服务