找出过去 30 天内首次上架的新商品,统计每个新品在上架后 14 天内的累计销量、累计浏览量和加购转化率
经典数据分析 SQL 面试题:新品上市表现评估
1. 题目背景
在电商业务中,实时监控新商品的上市表现至关重要。业务部门通常需要评估新品上架初期的“爆发力”,以便及时调整库存和推广策略。
面试要求:
找出过去 30 天内(以 2023-11-01 为当天)首次上架的新商品,统计每个新品在上架后 14 天内(含上架当天)的:
- 累计销量(
buy行为的quantity总和) - 累计浏览量(
view行为的总次数) - 加购转化率(加购独立用户数 UV / 浏览独立用户数 UV,若浏览 UV 为 0 则输出 0)
2. 示例数据
表 1:商品维表 dim_product
该表记录了商品的上架日期。
| product_id | product_name | launch_date | status |
|---|---|---|---|
| 101 | iPhone 15 Pro | 2023-10-15 | active |
| 102 | iPad Air 6 | 2023-10-25 | active |
| 103 | MacBook Air M3 | 2023-09-01 | active |
| 104 | AirPods Max 2 | 2023-10-01 | active |
| 105 | Apple Watch S9 | 2023-10-29 | active |
表 2:用户行为事实表 fact_user_behavior
该表记录了用户对商品的操作行为。
| action_id | user_id | product_id | action_type | action_date | quantity |
|---|---|---|---|---|---|
| 1 | U01 | 101 | view | 2023-10-15 | NULL |
| 2 | U01 | 101 | cart | 2023-10-15 | NULL |
| 3 | U01 | 101 | buy | 2023-10-16 | 2 |
| 4 | U02 | 101 | view | 2023-10-20 | NULL |
| 5 | U02 | 101 | buy | 2023-10-21 | 1 |
| 6 | U03 | 101 | view | 2023-10-30 | NULL |
| 7 | U01 | 102 | view | 2023-10-26 | NULL |
| 8 | U02 | 102 | view | 2023-10-26 | NULL |
| 9 | U02 | 102 | cart | 2023-10-27 | NULL |
| 10 | U03 | 103 | view | 2023-09-02 | NULL |
| 11 | U01 | 105 | view | 2023-10-30 | NULL |
3. 期望输出结果
(假设当前系统时间为 2023-11-01)
| product_id | product_name | launch_date | cumulative_sales | cumulative_views | cart_conversion_rate |
|---|---|---|---|---|---|
| 101 | iPhone 15 Pro | 2023-10-15 | 3 | 2 | 0.5000 |
| 102 | iPad Air 6 | 2023-10-25 | 0 | 2 | 0.5000 |
| 105 | Apple Watch S9 | 2023-10-29 | 0 | 1 | 0.0000 |
结果说明:
103和104商品上架时间早于2023-10-02(过去 30 天外),故排除。101在上架后 14 天内(10-15至10-28),行为 ID 6 发生在10-30属于 14 天外,被排除。期间 view 的 UV 是 2 (U01, U02),cart 的 UV 是 1 (U01),转化率为 1/2 = 0.5。销量为 2+1=3。
4. SQL 解答
sql
WITH new_products AS (
-- 1. 筛选出过去 30 天内首次上架的新商品
-- 生产环境通常使用 CURRENT_DATE(),此处用 '2023-11-01' 模拟当天
SELECT
product_id,
product_name,
launch_date
FROM dim_product
WHERE launch_date >= DATE_SUB('2023-11-01', INTERVAL 30 DAY)
AND launch_date <= '2023-11-01'
)
SELECT
p.product_id,
p.product_name,
p.launch_date,
-- 2. 统计 14 天内累计销量
COALESCE(SUM(CASE WHEN b.action_type = 'buy' THEN b.quantity ELSE 0 END), 0) AS cumulative_sales,
-- 3. 统计 14 天内累计浏览量(PV)
COALESCE(SUM(CASE WHEN b.action_type = 'view' THEN 1 ELSE 0 END), 0) AS cumulative_views,
-- 4. 计算加购转化率(加购UV / 浏览UV)
ROUND(
COALESCE(
COUNT(DISTINCT CASE WHEN b.action_type = 'cart' THEN b.user_id END) * 1.0
/ NULLIF(COUNT(DISTINCT CASE WHEN b.action_type = 'view' THEN b.user_id END), 0),
0
), 4
) AS cart_conversion_rate
FROM new_products p
LEFT JOIN fact_user_behavior b
ON p.product_id = b.product_id
-- 5. 限制行为必须发生在上架后的 14 天内(含当天)
AND b.action_date >= p.launch_date
AND b.action_date <= DATE_ADD(p.launch_date, INTERVAL 13 DAY)
GROUP BY
p.product_id,
p.product_name,
p.launch_date
ORDER BY
p.product_id;
5. 面试官视角:SQL 深度分析与答题技巧
此题看似基础,但在大厂面试中含金量极高,主要考察候选人处理“动态时间窗口”、“数据倾斜与清洗”以及“指标健壮性”的能力。
① 核心考点 1:动态关联条件的运用 (ON vs WHERE)
- 误区:新手常将
b.action_date <= DATE_ADD(...)的过滤条件写在WHERE子句中。 - 痛点:若写在
WHERE中,一旦某个新商品在上架 14 天内没有任何用户行为(如上面的105),在LEFT JOIN后这些记录会因为WHERE的过滤而被彻底排除。 - 解题技巧:必须把时间窗口限制条件写在
LEFT JOIN的ON子句中。这样能确保即使没有行为数据,新品依然会保留在结果集中,且各项指标显示为0或NULL。
② 核心考点 2:指标口径的精准还原 (转化率算法)
- 转化率定义:电商中“转化率”通常分为 UV 转化率(人数)和 PV 转化率(次数)。
- 本题要求:加购人数 / 浏览人数 (UV 转化)。因此使用
COUNT(DISTINCT user_id)。 - 注意条件嵌套:
COUNT(DISTINCT CASE WHEN action_type = 'cart' THEN user_id END)可以精准提取出有过加购行为的独立用户数。
- 本题要求:加购人数 / 浏览人数 (UV 转化)。因此使用
③ 核心考点 3:防错设计(除以 0 风险与 NULL 值处理)
- 除零错误 (Division by zero):如果某个新品只有加购,或者根本没有浏览量,直接相除会导致 SQL 报错崩溃。
- 解决方案:
- 使用
NULLIF(expression, 0):当浏览 UV 为 0 时,将其转换为NULL。 - 任何数除以
NULL都会得到NULL,最后通过COALESCE(..., 0)将NULL转换为0,保证了代码在任何极端数据下的健壮性。
- 使用
④ 面试加分项:大表关联优化思维
如果面试官追问:“如果 fact_user_behavior 有百亿级数据,这个 SQL 该怎么优化?”
- 追问回答方向:
- 分区裁剪:用户行为表通常按天分区。由于新商品最长只上架 30 天,且我们只关心上架后 14 天的数据,因此行为表最多只需要扫描过去 44 天的数据(30天前上架 + 14天观察期)。可以在 JOIN 前,对
fact_user_behavior进行分区过滤(WHERE action_date >= DATE_SUB(..., 44))。 - 避免笛卡尔积:先在子查询中对行为表按
product_id进行轻度聚合(过滤出 14 天内的行为),然后再与新品表进行LEFT JOIN。
- 分区裁剪:用户行为表通常按天分区。由于新商品最长只上架 30 天,且我们只关心上架后 14 天的数据,因此行为表最多只需要扫描过去 44 天的数据(30天前上架 + 14天观察期)。可以在 JOIN 前,对