跳到主要内容

美团大数据面试SQL-外卖用户复购周期分析

⚠️ 待修正

一、题目背景

这道题来自美团的数据分析岗面试。美团是本地生活服务(外卖、到店、酒旅),数据分析师需要从海量业务数据中挖掘洞见。

业务场景:用户消费行为相关需求在日常工作中频繁出现,这类型的SQL题是面试高频考点。

一、题目

现有一张用户下单记录表 t10_order_record,记录了每位用户每次下单的时间。请计算每个用户的平均复购周期(即相邻两次下单之间的平均天数)。

平均复购周期 = 所有相邻下单间隔天数的平均值。仅下单1次的用户不计算此指标。

用户下单记录表 t10_order_record:

+----------+----------+---------------------+
| order_id | user_id | order_time |
+----------+----------+---------------------+
| O001 | u01 | 2023-03-01 10:00:00 |
| O002 | u01 | 2023-03-03 10:00:00 |
| O003 | u01 | 2023-03-07 10:00:00 |
| O004 | u01 | 2023-03-12 10:00:00 |
| O005 | u02 | 2023-03-02 12:00:00 |
| O006 | u02 | 2023-03-05 12:00:00 |
| O007 | u02 | 2023-03-10 12:00:00 |
| O008 | u03 | 2023-03-01 18:00:00 |
| O009 | u03 | 2023-03-02 18:00:00 |
| O010 | u04 | 2023-03-03 09:00:00 |
+----------+----------+---------------------+

三、思路分析

复购周期是衡量用户粘性的重要指标,需要计算相邻订单的时间间隔。

解题步骤

  1. 使用 LEAD(或LAG)获取每个用户下一次下单时间;
  2. 计算相邻两次下单的间隔天数 datediff
  3. 按用户求平均间隔天数;
维度评分
题目难度⭐️⭐️⭐️
题目清晰度⭐️⭐️⭐️⭐️⭐️
业务常见度⭐️⭐️⭐️⭐️⭐️

四、逐步推导

1. 使用LEAD获取下次下单时间,计算间隔天数

执行SQL

select user_id,
order_id,
order_time,
lead(order_time, 1) over (partition by user_id order by order_time) as next_order_time,
datediff(lead(order_time, 1) over (partition by user_id order by order_time), order_time) as interval_days
from t10_order_record

执行结果

+----------+----------+---------------------+---------------------+---------------+
| user_id | order_id | order_time | next_order_time | interval_days |
+----------+----------+---------------------+---------------------+---------------+
| u01 | O001 | 2023-03-01 10:00:00 | 2023-03-03 10:00:00 | 2 |
| u01 | O002 | 2023-03-03 10:00:00 | 2023-03-07 10:00:00 | 4 |
| u01 | O003 | 2023-03-07 10:00:00 | 2023-03-12 10:00:00 | 5 |
| u01 | O004 | 2023-03-12 10:00:00 | NULL | NULL |
| u02 | O005 | 2023-03-02 12:00:00 | 2023-03-05 12:00:00 | 3 |
| u02 | O006 | 2023-03-05 12:00:00 | 2023-03-10 12:00:00 | 5 |
| u02 | O007 | 2023-03-10 12:00:00 | NULL | NULL |
| u03 | O008 | 2023-03-01 18:00:00 | 2023-03-02 18:00:00 | 1 |
| u03 | O009 | 2023-03-02 18:00:00 | NULL | NULL |
| u04 | O010 | 2023-03-03 09:00:00 | NULL | NULL |
+----------+----------+---------------------+---------------------+---------------+

2. 计算每个用户的平均复购周期

执行SQL

select user_id,
count(1) as order_cnt,
round(avg(interval_days), 1) as avg_repurchase_days
from (
select user_id,
order_id,
order_time,
datediff(
lead(order_time, 1) over (partition by user_id order by order_time),
order_time
) as interval_days
from t10_order_record
) t
where interval_days is not null
group by user_id
order by user_id

执行结果

+----------+-----------+----------------------+
| user_id | order_cnt | avg_repurchase_days |
+----------+-----------+----------------------+
| u01 | 3 | 3.7 |
| u02 | 2 | 4.0 |
| u03 | 1 | 1.0 |
+----------+-----------+----------------------+

u01下单4次(3个间隔),平均每3.7天复购一次,粘性较高;u04仅下单1次,无法计算复购周期。

五、常见坑点

坑1:NULL值的隐式处理 — 聚合函数跳过NULL,窗口函数不跳过。WHERE需显式过滤或用COALESCE替代。

坑2:数据类型不一致导致JOIN失效 — string vs int隐式转换可能触发全表扫描,性能骤降。

六、举一反三

  1. 扩展到N单间隔:rn <= 2改为rn <= N,计算到第N次购买的累计间隔

  2. 按品类/渠道对比:GROUP BY加category/channel,不同品类的复购间隔差异

  3. 间隔分布分层:0-1天/2-3天/4-7天/8-14天/15+天分段统计用户占比

七、知识点总结

考点说明
LAG / LEAD获取前/后一行数据,用于环比计算、状态变更检测
GROUP BY + 聚合函数分组聚合是数据分析的基础,配合HAVING筛选分组结果
日期函数DATEDIFF / DATE_ADD / unix_timestamp处理日期运算
NULL值处理NULL在聚合和窗口函数中的差异,COALESCE/NVL的替代方案

八、建表语句和数据插入

点击展开 DDL & DML
-- 建表语句
CREATE TABLE t10_order_record (
order_id string COMMENT '订单ID',
user_id string COMMENT '用户ID',
order_time string COMMENT '下单时间'
) COMMENT '用户下单记录表';

-- 数据插入
INSERT INTO t10_order_record VALUES
('O001', 'u01', '2023-03-01 10:00:00'),
('O002', 'u01', '2023-03-03 10:00:00'),
('O003', 'u01', '2023-03-07 10:00:00'),
('O004', 'u01', '2023-03-12 10:00:00'),
('O005', 'u02', '2023-03-02 12:00:00'),
('O006', 'u02', '2023-03-05 12:00:00'),
('O007', 'u02', '2023-03-10 12:00:00'),
('O008', 'u03', '2023-03-01 18:00:00'),
('O009', 'u03', '2023-03-02 18:00:00'),
('O010', 'u04', '2023-03-03 09:00:00');
📱关注公众号

「数据仓库技术」文章同步更新,不错过每一篇干货

微信公众号二维码
💬加群交流

备注「数据仓库技术」加入社群,每日一道大厂SQL真题

交流微信二维码

你可能还想看