客单价需用avg(real_paid_amount)且过滤取消/退款单和测试用户;转化率分母必须是会话数而非用户数,时间需严格对齐。

直接说结论:客单价用 AVG() 统计订单金额,转化率用 COUNT() 嵌套条件计算,但必须严格区分分母口径——不是访客数,而是“产生购买行为的独立用户数”或“进入结算页的会话数”,否则结果失真。
客单价:别直接 AVG(order_amount) 就完事
电商订单表里常有退款、测试单、合并单,AVG(order_amount) 会把异常值一起拉低。真实场景要先过滤:
- 排除
status IN ('cancelled', 'refunded')的订单 - 排除
user_id IN (SELECT user_id FROM users WHERE is_test = 1)的测试用户 - 若存在一单多商品,确认
order_amount是订单实付金额(不是商品小计),否则需先GROUP BY order_id汇总
示例语句:
SELECT AVG(real_paid_amount) FROM orders WHERE status = 'paid' AND created_at >= '2024-01-01';
转化率:分母错一个字,结果就全偏
常见错误是用 COUNT(DISTINCT user_id) 作分母去除以成交用户数——这算的是“用户转化率”,但运营更常看“会话转化率”(session-based)。两者的差异极大:
- 一个用户一天刷 10 次首页 → 会话数 ≈ 10,用户数 = 1
- 如果只统计用户,高活跃用户会严重稀释分母,导致转化率虚高
- 数据库没
session_id字段?可用user_id + DATE(created_at)或user_id + FLOOR(UNIX_TIMESTAMP(created_at)/1800)(按30分钟切片)模拟
正确写法(会话维度):
SELECT
COUNT(CASE WHEN order_id IS NOT NULL THEN 1 END) * 1.0 / COUNT(*) AS conv_rate
FROM (
SELECT
s.session_id,
MAX(o.order_id) AS order_id
FROM sessions s
LEFT JOIN orders o ON s.user_id = o.user_id
AND o.created_at BETWEEN s.start_time AND s.end_time
GROUP BY s.session_id
) t;
COUNT() 和 SUM() 在转化率里怎么选?
取决于你要回答的问题:
- “多少比例的会话最终下单?” → 用
COUNT(CASE WHEN ... THEN 1 END) / COUNT(*) - “平均每个会话带来多少订单?” → 用
SUM(CASE WHEN ... THEN 1 ELSE 0 END) / COUNT(*),等价于AVG(),但语义更清晰 - 注意:MySQL 中
COUNT(NULL)返回 0,COUNT(0)返回行数,别写成COUNT(IF(...))后漏掉ELSE 0,否则 NULL 不计入分母也不计入分子
最易被忽略的一点:时间对齐。统计转化率时,会话起始时间和订单创建时间必须落在同一时区、同一粒度(比如都用 UTC+8 的日切),且订单不能早于会话开始——否则会出现“未来订单提升历史转化率”这种逻辑漏洞。











