Skip to content

SQL 与取数

数据分析的 SQL 目标是「用最少的查询、按明确口径、把准确的数据取出来」。它与后端技术讲的角度不同:后端讲存储原理、索引与查询优化器,本页聚焦分析侧的取数心法——先想清楚粒度、再用可维护的方式组织查询,避免「看着对、算着错」。

取数三问(写 SQL 前)

  1. 粒度:我要的每一行代表什么?(每用户一行?每笔订单一行?每用户每天一行?)
    • 粒度不统一是 JOIN 后指标放大的头号来源——先写「预期行数」再验证。
  2. 口径:分子分母与业务定义一致吗?(活跃=启动过的用户?付费=支付成功的订单?)
  3. 窗口:统计时间是自然日/自然周?是否含当天?跨时区怎么算?用哪个时间字段(事件时间/业务时间)?

高频分析模式

窗口函数:行内对比

需求写法要点
每个用户首次/最近行为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 再 JOINJOIN 后再过滤会放大中间结果
预聚合反复要同一明细汇总建汇总层/物化视图,明细层仅用于深入下钻

查询优化原理(索引、执行计划、join 策略)属后端·数据库,分析侧只需掌握避免「全表反复扫」的直觉。

提效习惯

  • LIMIT 10 看结构,确认列名与类型再写完整查询;
  • 复用 CTE 而非反复贴子查询,可读性与可维护性都更好;
  • 常用口径沉淀为共享视图/逻辑表,团队共用,避免每人各自 DISTINCT 出不同数字;
  • 取数提交前自问:这个查询换个人能看懂口径吗?

常见坑速查

表现应对
JOIN 行数放大一对多 join 后指标虚高先定粒度,按粒度选主表与聚合顺序
DISTINCT 乱用大表全量 distinct 极慢预聚合或先缩范围
空值/脏值污染金额含 NULL 或负数清洗阶段统一规则(见分析工作流
分区列包函数明明限了时间还是全表扫date() 转换移到比较的另一侧
口径各自为政同一留存率两人算两样沉淀共享逻辑表/视图,口径成文
只取不出解释数据报表没说明取数结论附口径与局限

检查清单

  • [ ] 明确目标粒度,并对预期行数做了预估
  • [ ] 口径、时间窗口、时区规则与指标体系一致
  • [ ] 已用 LIMIT 探查表结构与抽样数据
  • [ ] 使用了分区裁剪与预聚合,避免全表反复扫描
  • [ ] 常用口径沉淀为共享视图/逻辑表
  • [ ] 数据通过总量等式与抽样抽查双重验证

相关:分析工作流 · 指标体系与埋点 · 存储与查询原理见后端·数据库

基于 VitePress 构建 · 内容以知识共享方式沉淀