You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用SQL查询用户首次产生正收入时的留存天数?

查询用户首次产生正收入时的留存天数

示例数据

user_id, creation_date, activity_date, net_revenue, retained_days

1, 2019/01/01, 2019/01/01, 0, 0
2, 2019/01/01, 2019/01/01, 0, 0

1, 2019/01/01, 2019/01/02, 0, 1
2, 2019/01/01, 2019/01/02, 0, 1

1, 2019/01/01, 2019/01/03, 0, 2
2, 2019/01/01, 2019/01/03, 0, 2
 
1, 2019/01/01, 2019/01/04, 5.5, 3
2, 2019/01/01, 2019/01/04, 0, 3

1, 2019/01/01, 2019/01/05, 5.5, 4
2, 2019/01/01, 2019/01/05, 3, 4

需求与期望输出

需要获取每个用户**首次产生正收入(net_revenue>0)**时对应的retained_days值,示例期望输出:

1, 3
2, 4

尝试过的错误SQL

写法1

SELECT DISTINCT uid, 
CASE
WHEN SUM(net_revenue) >0
THEN SUM(retained_days)
END AS ret_day_fst_purch
FROM table1 
GROUP BY 1

写法2

SELECT DISTINCT uid, 
activity_date,
CASE
WHEN SUM(net_revenue) >0
THEN SUM(retained_days)
END AS ret_day_fst_purch
FROM table1 
GROUP BY 1,2

上述写法错误原因:使用SUM()聚合函数会对所有记录的数值求和,而需求是获取单条首次正收入记录的retained_days,并非求和结果。

正确解决方案

方案1:使用窗口函数(通用且准确)

通过窗口函数ROW_NUMBER()对每个用户的正收入记录按日期排序,标记出第一条记录:

SELECT user_id, retained_days
FROM (
    SELECT 
        user_id,
        retained_days,
        -- 按用户分组,按活动日期升序排序,标记第一条记录
        ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY activity_date) AS record_rank
    FROM table1
    -- 只筛选正收入的记录
    WHERE net_revenue > 0
) ranked_records
-- 取每个用户的第一条正收入记录
WHERE record_rank = 1;

方案2:利用留存天数递增特性简化查询

由于示例中retained_days随activity_date递增,首次正收入对应的retained_days是该用户所有正收入记录中的最小值,因此可以直接聚合取最小值:

SELECT 
    user_id,
    MIN(retained_days) AS ret_day_fst_purch
FROM table1
WHERE net_revenue > 0
GROUP BY user_id;

这两种写法都能得到预期结果,方案1更通用,即使retained_days不严格递增也能准确获取首次正收入记录;方案2仅适用于retained_days与activity_date严格正相关的场景。

内容的提问来源于stack exchange,提问作者Nata

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 06:55:18