Snowflake SQL技术求助:每日及累计balance>0的唯一用户统计
解决方案
先明确需求对应逻辑
从你给出的期望输出来看,初始需求实际是累计到当日的、首次出现balance>0的唯一用户总数,而非单日活跃的用户数。下面分场景给出SQL实现:
场景1:实现你期望的累计唯一用户数(仅统计首次balance>0的用户)
首先得筛选出每个用户第一次出现balance>0的日期,再统计截止到每天有多少这类用户:
-- 先预处理:获取每个用户首次balance>0的日期 WITH user_first_active AS ( SELECT user_id, MIN(days) AS first_active_day FROM your_table WHERE balance > 0 GROUP BY user_id ) -- 关联原表所有日期,计算累计用户数 SELECT t.days, COUNT(DISTINCT u.user_id) AS unique_users FROM your_table t LEFT JOIN user_first_active u ON t.days >= u.first_active_day GROUP BY t.days ORDER BY t.days;
这个查询完全匹配你给出的期望结果:
- 用户1在2022/08/01首次达标,从这天起每天都计入统计
- 用户2在2022/08/05首次balance>0,从这天开始加入总数
- 用户3在2022/08/07首次达标,之后每天都被统计进去
场景2:如果是要统计单日balance>0的唯一用户数
如果你的初始需求确实是只计算当天balance>0的用户(比如2022/08/03只有用户1达标),那查询更简洁:
SELECT days, COUNT(DISTINCT user_id) AS unique_users FROM your_table WHERE balance > 0 GROUP BY days ORDER BY days;
关于窗口函数的补充说明
很多SQL引擎(比如MySQL)不支持COUNT(DISTINCT ...) OVER (...)这种窗口函数用法,所以用CTE预处理用户首次活跃日期是更通用的方案。如果你的SQL引擎支持(比如PostgreSQL),也可以用窗口函数直接累计计数:
WITH user_first_active AS ( SELECT user_id, MIN(days) AS first_active_day FROM your_table WHERE balance > 0 GROUP BY user_id ), all_dates AS ( SELECT DISTINCT days FROM your_table ) SELECT a.days, COUNT(u.user_id) OVER (ORDER BY a.days) AS unique_users FROM all_dates a LEFT JOIN user_first_active u ON a.days >= u.first_active_day ORDER BY a.days;
这个写法的结果和第一个方案完全一致。
内容的提问来源于stack exchange,提问作者Mr Khan
相关产品推荐
相关产品推荐

