SQL 与取数
数据分析的 SQL 目标是「用最少的查询、按明确口径、把准确的数据取出来」。它与后端技术讲的角度不同:后端讲存储原理、索引与查询优化器,本页聚焦分析侧的取数心法——先想清楚粒度、再用可维护的方式组织查询,避免「看着对、算着错」。
取数三问(写 SQL 前)
- 粒度:我要的每一行代表什么?(每用户一行?每笔订单一行?每用户每天一行?)
- 粒度不统一是 JOIN 后指标放大的头号来源——先写「预期行数」再验证。
- 口径:分子分母与业务定义一致吗?(活跃=启动过的用户?付费=支付成功的订单?)
- 口径与指标体系与埋点联动,一个指标只能有一个权威定义。
- 窗口:统计时间是自然日/自然周?是否含当天?跨时区怎么算?用哪个时间字段(事件时间/业务时间)?
高频分析模式
窗口函数:行内对比
| 需求 | 写法要点 |
|---|---|
| 每个用户首次/最近行为 | ROW_NUMBER() OVER (PARTITION BY uid ORDER BY ts) 取 =1 |
| 每用户历史累计 | SUM(...) OVER (PARTITION BY uid ORDER BY ts) |
| 环比上期 | LAG(value, 1) OVER (PARTITION BY ... ORDER BY period) |
示例:最近 7 天每日 DAU 环比
sql
WITH daily AS (
SELECT dt, COUNT(DISTINCT uid) AS dau
FROM events
WHERE dt BETWEEN '2026-08-25' AND '2026-08-31'
GROUP BY dt
)
SELECT dt, dau,
LAG(dau) OVER (ORDER BY dt) AS dau_prev,
ROUND((dau - LAG(dau) OVER (ORDER BY dt)) * 100.0 / LAG(dau) OVER (ORDER BY dt), 2) AS mom_pct
FROM daily
ORDER BY dt;条件聚合:一列算多组对比
在同一个 GROUP BY 内用 COUNT(DISTINCT CASE WHEN ... THEN uid END) 比较不同条件子集,比多次 join 自己更稳:
sql
SELECT channel,
COUNT(DISTINCT uid) AS users,
COUNT(DISTINCT CASE WHEN is_new = 1 THEN uid END) AS new_users,
COUNT(DISTINCT CASE WHEN paid_cnt > 0 THEN uid END) AS paying_users
FROM user_daily
WHERE dt = '2026-08-31'
GROUP BY channel;查询性能:先想三件事
| 手段 | 何时有效 | 注意 |
|---|---|---|
| 分区裁剪 | 明确只查某时间窗 | 别在分区列上包函数(WHERE date(ts)=... 会失去裁剪) |
| 过滤下推 | 大表先 WHERE 再 JOIN | JOIN 后再过滤会放大中间结果 |
| 预聚合 | 反复要同一明细汇总 | 建汇总层/物化视图,明细层仅用于深入下钻 |
查询优化原理(索引、执行计划、join 策略)属后端·数据库,分析侧只需掌握避免「全表反复扫」的直觉。
提效习惯
- 先
LIMIT 10看结构,确认列名与类型再写完整查询; - 复用 CTE 而非反复贴子查询,可读性与可维护性都更好;
- 常用口径沉淀为共享视图/逻辑表,团队共用,避免每人各自
DISTINCT出不同数字; - 取数提交前自问:这个查询换个人能看懂口径吗?
常见坑速查
| 坑 | 表现 | 应对 |
|---|---|---|
| JOIN 行数放大 | 一对多 join 后指标虚高 | 先定粒度,按粒度选主表与聚合顺序 |
| DISTINCT 乱用 | 大表全量 distinct 极慢 | 预聚合或先缩范围 |
| 空值/脏值污染 | 金额含 NULL 或负数 | 清洗阶段统一规则(见分析工作流) |
| 分区列包函数 | 明明限了时间还是全表扫 | 把 date() 转换移到比较的另一侧 |
| 口径各自为政 | 同一留存率两人算两样 | 沉淀共享逻辑表/视图,口径成文 |
| 只取不出解释 | 数据报表没说明 | 取数结论附口径与局限 |
检查清单
- [ ] 明确目标粒度,并对预期行数做了预估
- [ ] 口径、时间窗口、时区规则与指标体系一致
- [ ] 已用 LIMIT 探查表结构与抽样数据
- [ ] 使用了分区裁剪与预聚合,避免全表反复扫描
- [ ] 常用口径沉淀为共享视图/逻辑表
- [ ] 数据通过总量等式与抽样抽查双重验证