基于本文回答

播面 播面

文图音视,全方位拆解八股文
0
评论

计算用户领取优惠券到实际消费使用该券的转化率,并统计使用优惠券的平均时间间隔(领券后多少小时内使用)

面试题:优惠券领用双维度分析(转化率与核销时效)

在电商、O2O等业务场景中,优惠券是促进用户转化的重要手段。本题旨在考察候选人对漏斗转化分析以及时间跨度计算(时间差)的 SQL 编写能力及业务理解。


1. 场景数据准备

假设系统中有两张表:领券记录表 (coupon_receive)使用/消费记录表 (coupon_use)

表1:领券记录表 (coupon_receive)

user_id (用户ID) coupon_id (优惠券ID) receive_time (领券时间)
1001 C_01 2023-10-01 10:00:00
1002 C_01 2023-10-01 12:30:00
1003 C_02 2023-10-02 09:15:00
1004 C_01 2023-10-02 14:00:00
1005 C_03 2023-10-03 18:00:00
1001 C_02 2023-10-04 08:00:00

表2:用券/消费记录表 (coupon_use)

user_id (用户ID) coupon_id (优惠券ID) order_id (订单ID) use_time (使用时间)
1001 C_01 ORD_9901 2023-10-01 10:45:00
1002 C_01 ORD_9902 2023-10-01 22:30:00
1005 C_03 ORD_9903 2023-10-05 18:00:00
1001 C_02 ORD_9904 2023-10-04 08:15:00

注:用户 1003 领券后未消费;用户 1004 领券后未消费。


2. 面试题目要求

请编写一条 SQL 语句,计算出以下两个指标:

  1. 券转化率 (Conversion Rate):实际使用优惠券的记录数占总领券记录数的比例(结果以百分比形式展现,保留2位小数)。
  2. 平均使用时间间隔 (Average Interval Hours):从领券到用券的平均时间间隔,单位为小时(保留2位小数)。

提示:使用时间必须晚于或等于领券时间才算作有效转化。


3. 标准 SQL 解答 (基于 MySQL 8.0+)

sql
SELECT 
    -- 1. 计算总领券量
    COUNT(r.user_id) AS total_received,
    
    -- 2. 计算实际使用量
    COUNT(u.user_id) AS total_used,
    
    -- 3. 计算转化率 (用券量 / 领券量)
    ROUND(
        COUNT(u.user_id) * 100.0 / COUNT(r.user_id), 
        2
    ) AS conversion_rate_pct,
    
    -- 4. 计算平均用券时间间隔(小时)
    ROUND(
        AVG(TIMESTAMPDIFF(SECOND, r.receive_time, u.use_time) / 3600.0), 
        2
    ) AS avg_use_interval_hours
FROM 
    coupon_receive r
LEFT JOIN 
    coupon_use u 
ON 
    r.user_id = u.user_id 
    AND r.coupon_id = u.coupon_id 
    AND u.use_time >= r.receive_time;

预期输出结果:

total_received total_used conversion_rate_pct avg_use_interval_hours
6 4 66.67 15.19

(解析提示:有效用券记录共4条。时间差分别为:1001-C_01:0.75小时;1002-C_01:10.0小时;1005-C_03:48.0小时;1001-C_02:0.25小时。平均值:(0.75 + 10.0 + 48.0 + 0.25) / 4 = 14.75小时。若用秒换算更精确:(2700 + 36000 + 172800 + 900) / 4 / 3600 = 14.75小时)


4. 核心考点与面试官心理解析

考点一:LEFT JOIN 的合理运用(漏斗分析基础)

  • 理解意图:计算转化率必须保留分母(所有领券的用户),所以必须以领券表 coupon_receive主表进行 LEFT JOIN。如果错误地使用了 INNER JOIN,未用券的数据(1003、1004)就会被过滤掉,导致转化率计算恒为 100%。
  • 加分项:在 ON 条件中直接限制 u.use_time >= r.receive_time,防止“先消费后补券”的异常脏数据干扰统计。

考点二:聚合函数 COUNT 的特征

  • 理解意图COUNT(r.user_id) 会统计所有领券记录,而 COUNT(u.user_id) 仅统计 LEFT JOIN 成功匹配到的非 NULL 记录。这能直接在一行 SQL 中优雅地解决分子和分母的计算,避免写复杂的子查询。

考点三:高精度时间差计算 (TIMESTAMPDIFF / DATEDIFF)

  • 避坑指南:很多候选人会直接使用 DATEDIFF(u.use_time, r.receive_time),但 DATEDIFF 仅计算天数差,无法精确到小时。
  • 正确做法:使用 TIMESTAMPDIFF(SECOND, ...) 计算秒数差,再除以 3600.0 转换为小时。注意除数要带小数点(如 3600.0),在某些数据库(如 SQL Server/PostgreSQL)中,整除会丢失小数精度。

考点四:业务思维扩展(面试追问准备)

如果候选人完美答出上述 SQL,面试官通常会进行以下追问以考察其业务Sense:

  1. 追问一:如果同一个用户多次领取同一张券,又多次使用,你的 Join 会不会产生笛卡尔积?
    • 应对策略:在实际业务中,券实例通常有唯一的 get_id (领券实例ID)。若无此ID,需在 JOIN 时加上时间顺序逻辑(如:用券时间必须在领券时间之后,且是距离最近的一次领券)。
  2. 追问二:如何按优惠券维度 (coupon_id) 统计这些指标?
    • 应对策略:在 SQL 结尾加上 GROUP BY r.coupon_id,并在 SELECT 中加入 r.coupon_id 即可。
00:00
00:00