LTV是用户生命周期价值,不能直接用SUM(revenue)因其忽略时间价值、留存衰减与预测周期;需分historical(已发生净收入)与predictive(未来预测)两部分,且须严格清洗数据、对齐口径。

什么是 LTV,为什么不能直接用 SUM(revenue)?
用户生命周期价值(LTV)不是简单把某个用户所有订单金额加总。它必须考虑时间价值、留存衰减和预测周期——比如一个用户今年买了 100 元,明年大概率不会买同样多,后年更可能流失。直接 SUM(revenue) 会高估真实价值,尤其对新用户或长尾用户偏差极大。
实操中,LTV 通常拆成两部分:historical LTV(已发生)和 predictive LTV(未来预测)。多数业务场景先聚焦 historical LTV,它可直接从数据库算出,且能校准预测模型。
计算 historical LTV 的标准 SQL 写法
核心逻辑是:按 user_id 聚合其全部支付成功订单的净收入(排除退款、优惠券虚增)。关键点不在聚合函数本身,而在数据清洗和口径对齐:
- 必须过滤状态字段,例如只取
order_status = 'paid'或payment_status = 'succeeded',避免未支付/取消单混入 - 推荐用
COALESCE(refund_amount, 0)处理空退款值,否则revenue - refund_amount会因 NULL 变成 NULL - 若订单表含多币种,需统一换算为基准货币(如 USD),不能直接加总原始
amount - 时间范围建议显式限定,比如
WHERE created_at >= '2022-01-01',避免全表扫描拖慢查询
示例(PostgreSQL):
SELECT user_id, SUM(COALESCE(amount, 0) - COALESCE(refund_amount, 0)) AS historical_ltv FROM orders WHERE payment_status = 'succeeded' AND created_at >= '2022-01-01' GROUP BY user_id;
常见错误:把 LTV 和 ARPU、ARPPU 混在一起
ARPU(每用户平均收入)是分母为「活跃用户数」的均值,ARPPU(每付费用户平均收入)分母是「付费用户数」,而 LTV 是单个用户的累计值。三者统计粒度和业务含义完全不同:
- 误用
AVG(historical_ltv)当作 LTV:这是「平均 LTV」,掩盖了长尾分布(少数高价值用户拉高均值) - 在 LTV 计算中混入未付费用户:这类用户 historical_ltv=0,但放入 GROUP BY 会稀释结果,应单独分析留存率而非强行计入
- 用月度订单聚合替代用户级聚合:例如
GROUP BY user_id, DATE_TRUNC('month', created_at)再求和,容易重复计费或漏掉跨月订单
进阶:加入时间衰减因子的简易 LTV 估算
如果需要粗略反映“近期收入比远期更重要”,可在 historical LTV 上加指数衰减。不依赖复杂模型,纯 SQL 就能做:
- 以天为单位,用
EXP(-0.001 * (CURRENT_DATE - created_at))作为权重(0.001 对应约 2 年半的半衰期) - 注意 PostgreSQL 需开启
plpgsql扩展才能用EXP(),MySQL 用POW(2.71828, ...)替代 - 衰减后数值不再具财务意义,仅用于排序或分层(如识别“高潜力但近期沉寂”用户)
示例(加权 LTV):
SELECT
user_id,
SUM((COALESCE(amount, 0) - COALESCE(refund_amount, 0))
* EXP(-0.001 * (CURRENT_DATE - created_at))) AS weighted_ltv
FROM orders
WHERE payment_status = 'succeeded'
GROUP BY user_id;真正难的不是写这条 SQL,而是定义清楚:你算 LTV 是为了做用户分群、预算分配,还是给风控模型打标?不同目标下,“历史”要回溯多久、“收入”是否包含毛利、要不要剔除获客成本,答案都不同。这些决策不会出现在 SQL 里,但会决定结果有没有用。










