ab测试group by多字段需先过滤有效分组并清洗数据,用count(distinct user_id)防重复计数,加样本量校验和时间窗口对齐。

GROUP BY 多字段组合必须明确实验分组和指标维度
AB测试结果分析的核心是把用户按实验分组(如 experiment_group)和业务维度(如 country、device_type、signup_date::date)切片,再聚合关键指标。直接写 GROUP BY experiment_group, country, device_type 是可行的,但容易漏掉空值或类型不一致问题——比如 experiment_group 为 NULL 的对照组未清洗,或 device_type 存在大小写混用('iOS' 和 'ios' 被当两个组)。建议先用 WHERE experiment_group IN ('control', 'treatment') 过滤有效分组,并对字符串字段统一小写:LOWER(device_type)。
聚合函数选 COUNT(DISTINCT user_id) 而非 COUNT(*)
AB测试中用户可能多次触发事件(如点击按钮),用 COUNT(*) 会重复计数,导致转化率虚高。真实指标应基于去重用户数。例如计算各组点击率:
SELECT
experiment_group,
COUNT(DISTINCT CASE WHEN event = 'click' THEN user_id END) AS click_users,
COUNT(DISTINCT user_id) AS total_users,
ROUND(100.0 * click_users / NULLIF(total_users, 0), 2) AS ctr_pct
FROM events
WHERE event IN ('view', 'click') AND experiment_group IS NOT NULL
GROUP BY experiment_group;
注意三点:
- CASE WHEN ... THEN user_id END 确保只对目标事件计用户,不是计事件次数
- NULLIF(total_users, 0) 避免除零错误
- ROUND(..., 2) 控制小数位,避免浮点精度干扰判断
多维交叉时警惕数据稀疏导致的统计不可靠
加一个维度(比如从 GROUP BY experiment_group, country 扩展到 GROUP BY experiment_group, country, device_type)会让每个分组样本量快速下降。当某组 COUNT(DISTINCT user_id) 时,CTR 或留存率波动极大,不能直接下结论。实操中建议:
- 在 SELECT 中加上 <code>COUNT(DISTINCT user_id) AS n_users
- 查询后用外部工具(如 Python/Pandas)过滤掉 n_users 的行再分析
- 若必须展示,对小样本组标注「样本不足,置信度低」而不是留空或填 0
时间窗口不一致是 AB 测试 GROUP BY 最常被忽略的坑
实验启动时间、用户进入实验时间、事件发生时间三者常不一致。错误做法是直接用 event_time::date 分组——这会混入实验前的行为。正确方式是绑定用户首次进入实验的时间(通常存在 user_exposure 表中),然后 JOIN 后按曝光日期切片:GROUP BY experiment_group, exposure_date::date。如果只有事件表,至少用 WHERE event_time >= '2024-05-01'(实验开始日)硬过滤,否则 GROUP BY 出来的“首日转化率”实际是全量历史数据的平均值。











