转化率本质是“成功事件数÷初始事件数”,关键在明确漏斗起点与终点、时间范围及去重维度,需通过JOIN或EXISTS确保“先A后B”逻辑,且分子分母必须同粒度对齐。

转化率本质是“成功事件数 ÷ 初始事件数”,用 SQL 实现的关键不是套公式,而是先理清业务口径:谁是漏斗起点?什么是“转化成功”?时间范围和去重逻辑怎么定?
明确转化漏斗的两个关键节点
比如电商下单转化率,起点通常是“商品曝光”或“详情页访问”,终点是“支付成功”。不能直接用订单表除以用户表——必须保证分子分母在相同维度(如按天、按用户、按商品)对齐,且分母里已包含分子。
- 错误写法:
COUNT(DISTINCT 订单ID) / COUNT(DISTINCT 用户ID)(用户没曝光就下单?逻辑断裂) - 正确思路:先关联曝光日志和订单表,限定“当天曝光过某商品,当天又下单该商品”的用户/会话
用 JOIN 或 EXISTS 抓住“先后关系”
转化不是独立统计两张表,而是要确认“先有A,后有B”。推荐用 LEFT JOIN + 条件过滤,或 WHERE EXISTS 子查询。
- 示例(点击→下单):
SELECT
c.dt,
COUNT(DISTINCT o.user_id) * 1.0 / NULLIF(COUNT(DISTINCT c.user_id), 0) AS cvr
FROM click_log c
LEFT JOIN order_log o
ON c.user_id = o.user_id
AND c.item_id = o.item_id
AND o.event_time >= c.event_time
AND o.event_time < c.event_time + INTERVAL '1 day'
WHERE c.dt = '2024-06-01'
GROUP BY c.dt; - 注意:用
NULLIF避免除零;时间窗口(如1天内)必须业务认可;JOIN 条件里补上item_id是防跨商品误算
去重与粒度必须一致
用户级转化率、会话级转化率、商品曝光次级转化率,结果差异巨大。建模前必须约定好“一个分母单位是什么”。
- 如果分母是“用户日活”,分子就得是“当日完成转化的去重用户数”
- 如果分母是“商品曝光次数”,分子就得是“对应曝光ID后续产生订单的曝光次数”(需用曝光ID关联订单)
- 常见坑:分母按 user_id 去重,分子却按 order_id 统计——数量级直接失真
加一层 WITH 语句让逻辑更清晰
复杂转化路径(如 浏览→加购→下单→支付)建议拆步建模,用 CTE 分层定义各环节行为,再逐级 JOIN。
- 例如:
WITH view AS (SELECT DISTINCT user_id, dt FROM page_view WHERE page='item'), cart AS (SELECT DISTINCT user_id, dt FROM cart_add), pay AS (SELECT DISTINCT user_id, dt FROM order_pay),再连表算各阶段转化 - 好处:每步可单独验证数据量、排查黑盒;后续复用方便(比如加购率、支付成功率直接从同一基础集取)










