如何筛选并统计满足特定月度曝光量条件的唯一user_id
解决方法
核心思路是先统计每个用户每月的总曝光量,再基于这个统计结果直接筛选符合条件的用户,不需要临时表,用分组和聚合函数就能搞定。
第一步:统计用户月度总曝光
先将原数据按用户、年份、月份分组,计算每个用户每个月的总曝光量(原表是每次曝光一条记录,所以需要对impressions求和)。不同数据库的日期处理函数略有不同,举两个常用示例:
MySQL/MariaDB 写法
SELECT user_id, YEAR(date) AS year, MONTH(date) AS month, SUM(impressions) AS monthly_imp FROM your_table_name GROUP BY user_id, YEAR(date), MONTH(date)
PostgreSQL 写法
SELECT user_id, DATE_TRUNC('month', date) AS month_year, SUM(impressions) AS monthly_imp FROM your_table_name GROUP BY user_id, DATE_TRUNC('month', date)
第二步:筛选符合条件的用户
基于上面的月度统计结果,找出同一年中,既有某个月曝光量<3,又有其他月份曝光量>3的用户。直接用分组和HAVING子句就能实现,完整SQL示例(以MySQL为例):
-- 列出所有符合条件的用户ID SELECT user_id FROM ( -- 子查询:统计每个用户每月总曝光 SELECT user_id, YEAR(date) AS year, SUM(impressions) AS monthly_imp FROM your_table_name GROUP BY user_id, YEAR(date), MONTH(date) ) AS user_monthly_stats GROUP BY user_id, year HAVING -- 存在至少一个月曝光量<3 MIN(CASE WHEN monthly_imp < 3 THEN 1 ELSE 0 END) = 1 AND -- 存在至少一个月曝光量>3 MIN(CASE WHEN monthly_imp > 3 THEN 1 ELSE 0 END) = 1; -- 如果要直接统计符合条件的用户数量,把上面的SELECT改为: -- SELECT COUNT(DISTINCT user_id) AS qualified_user_count
逻辑说明
- 子查询先算出每个用户每个月的总曝光,确保我们是按月份维度分析。
GROUP BY user_id, year保证我们是在同一年的范围内判断用户的曝光情况,避免跨年度数据干扰。HAVING里的CASE语句会把符合条件的月份标记为1,不符合的为0;MIN(...) = 1意味着该用户至少有一个月份满足对应条件(只要有一个1,最小值就是1),两个条件同时满足就符合要求。
如果是其他数据库(比如SQL Server),只需要调整日期处理函数(比如用DATEPART(year, date)代替YEAR(date)),核心逻辑完全一致。
内容的提问来源于stack exchange,提问作者katrin_melody
相关产品推荐
相关产品推荐

