统计退货订单中,从“买家发起申请 -> 商家同意 -> 买家寄回 -> 平台退款完成”每个节点的平均处理时长
面试真题:电商退货流程节点平均处理时长统计
1. 题目背景
在电商业务中,退货体验是影响用户复购率的关键因素。为了监控退货链路的效率,我们需要统计退货流程中各个核心节点之间的平均处理耗时。
请根据给定的退款操作日志表,计算出以下三个阶段的平均处理时长(单位:小时,保留2位小数):
- 申请到同意:买家发起申请 -> 商家同意
- 同意到寄回:商家同意 -> 买家寄回
- 寄回到退款:买家寄回 -> 平台退款完成
2. 候选数据源
退货日志表:refund_log
| order_id (订单ID) | status (操作状态) | log_time (操作时间) |
|---|---|---|
| 1001 | 买家发起申请 | 2023-10-01 10:00:00 |
| 1001 | 商家同意 | 2023-10-01 12:00:00 |
| 1001 | 买家寄回 | 2023-10-01 18:00:00 |
| 1001 | 平台退款完成 | 2023-10-02 18:00:00 |
| 1002 | 买家发起申请 | 2023-10-02 08:00:00 |
| 1002 | 商家同意 | 2023-10-02 12:00:00 |
| 1002 | 买家寄回 | 2023-10-03 12:00:00 |
| 1002 | 平台退款完成 | 2023-10-04 12:00:00 |
| 1003 | 买家发起申请 | 2023-10-04 09:00:00 |
| 1003 | 商家同意 | 2023-10-04 11:00:00 |
注:订单1003目前只进行到“商家同意”阶段。
3. 期望输出结果
| avg_apply_to_agree_hours (平均申请-同意/小时) | avg_agree_to_ship_hours (平均同意-寄回/小时) | avg_ship_to_refund_hours (平均寄回-退款/小时) |
|---|---|---|
| 3.00 | 15.00 | 24.00 |
计算逻辑说明:
- 申请-同意:(1001单2小时 + 1002单4小时 + 1003单2小时) / 3 = 3.00小时
- 同意-寄回:(1001单6小时 + 1002单24小时) / 2 = 15.00小时
- 寄回-退款:(1001单24小时 + 1002单24小时) / 2 = 24.00小时
4. 解决方案 SQL (MySQL 8.0+)
sql
WITH pv_refund AS (
-- 1. 行转列:将同一个订单的各个节点时间拉平到同一行
SELECT
order_id,
MAX(CASE WHEN status = '买家发起申请' THEN log_time END) AS apply_time,
MAX(CASE WHEN status = '商家同意' THEN log_time END) AS agree_time,
MAX(CASE WHEN status = '买家寄回' THEN log_time END) AS ship_time,
MAX(CASE WHEN status = '平台退款完成' THEN log_time END) AS refund_time
FROM refund_log
GROUP BY order_id
)
-- 2. 计算各个阶段的差值并求平均值
SELECT
ROUND(AVG(TIMESTAMPDIFF(SECOND, apply_time, agree_time) / 3600.0), 2) AS avg_apply_to_agree_hours,
ROUND(AVG(TIMESTAMPDIFF(SECOND, agree_time, ship_time) / 3600.0), 2) AS avg_agree_to_ship_hours,
ROUND(AVG(TIMESTAMPDIFF(SECOND, ship_time, refund_time) / 3600.0), 2) AS avg_ship_to_refund_hours
FROM pv_refund;
5. 剖析与面试应对技巧
此题是标准的“漏斗分析/时效分析”场景,在电商、物流、客服域面试中出现频率极高。面试官主要考察以下几个技术维度和业务思考:
技术细节解析
行转列(Pivot)的应用:
原始数据是“纵表”(每个订单有多行状态日志),如果不做处理,直接使用JOIN关联自身会产生大量的笛卡尔积,且 SQL 极难维护。
最优解法是使用GROUP BY + CASE WHEN进行条件聚合,将纵表转为“横表”(即一个订单只有一行,包含所有节点的时间戳)。空值(NULL)的自动处理:
在AVG聚合函数中,MySQL 会自动忽略 NULL 值。例如订单 1003 的ship_time和refund_time为 NULL,那么在计算avg_agree_to_ship_hours时,该单不会被计入分子和分母中,保证了均值的准确性。时间差精度问题:
避免直接使用TIMESTAMPDIFF(HOUR, ...)。因为该函数会直接向下取整(如 1小时50分钟 会被计算为 1小时),导致严重精度丢失。
标准实践:先计算SECOND(秒)或MINUTE(分钟),再除以相应的系数(3600.0或60.0),最后用ROUND保留小数。
面试加分项(主动向面试官提及)
- 脏数据与逆流程处理:在实际业务中,可能存在“买家撤回申请后重新申请”或“商家拒绝后买家再次修改”的情况。如果在面试中,你能主动问一句:“如果存在多次重复的节点(例如多次发起申请),是以第一次为准还是最后一次为准?”,面试官会对你的业务敏感度刮目相看。
- 应对方案:如果按最后一次,可以在行转列时,将
MAX(log_time)作为取值标准。
- 应对方案:如果按最后一次,可以在行转列时,将
- 大表性能优化:如果
refund_log表每天有千万级数据,直接GROUP BY全表会引发 OOM。实际工作中应该限制时间分区,比如WHERE log_time >= '2023-10-01 00:00:00'。
右滑查看面试常问