如何用SQL对去年11月以来各月创建的用户抽样100-200条?
当然可以用SQL搞定这个需求!分月抽样100-200条用户并合并结果完全没问题,具体写法会根据你使用的数据库略有不同,我给你整理了几种主流数据库的实操方案:
MySQL/MariaDB 实现方式
用窗口函数ROW_NUMBER()按月份分组,给每个月的用户随机排序后取前N条,自动合并所有月份的结果:
WITH monthly_users AS ( SELECT *, DATE_FORMAT(created_at, '%Y-%m') AS month, ROW_NUMBER() OVER (PARTITION BY DATE_FORMAT(created_at, '%Y-%m') ORDER BY RAND()) AS row_num FROM YOUR_TABLE_NAME WHERE created_at >= '2023-11-01' -- 替换成去年11月的实际起始日期 ) SELECT * FROM monthly_users WHERE row_num <= 100; -- 每个月抽100条,要抽200条就改成<=200
如果想每个月随机抽取100-200之间的数量,可以把row_num <= 100改成row_num <= FLOOR(100 + RAND()*101),不过每次执行抽取数量会变化;要是想固定每个月的抽取数,可以先定义各月目标数再关联筛选。
PostgreSQL 实现方式
逻辑和MySQL类似,用RANDOM()生成随机排序:
WITH monthly_users AS ( SELECT *, TO_CHAR(created_at, 'YYYY-MM') AS month, ROW_NUMBER() OVER (PARTITION BY TO_CHAR(created_at, 'YYYY-MM') ORDER BY RANDOM()) AS row_num FROM YOUR_TABLE_NAME WHERE created_at >= '2023-11-01' ) SELECT * FROM monthly_users WHERE row_num <= 100;
SQL Server 实现方式
用NEWID()来实现随机排序,配合窗口函数分月抽样:
WITH monthly_users AS ( SELECT *, FORMAT(created_at, 'yyyy-MM') AS month, ROW_NUMBER() OVER (PARTITION BY FORMAT(created_at, 'yyyy-MM') ORDER BY NEWID()) AS row_num FROM YOUR_TABLE_NAME WHERE created_at >= '2023-11-01' ) SELECT * FROM monthly_users WHERE row_num <= 100;
备选方案:UNION ALL 拼接
如果你的数据库不支持CTE(比如老版本MySQL),可以用UNION ALL把每个月的查询拼起来,虽然繁琐但直观:
SELECT * FROM YOUR_TABLE_NAME WHERE created_at BETWEEN '2023-11-01' AND '2023-11-30' ORDER BY RAND() LIMIT 100 UNION ALL SELECT * FROM YOUR_TABLE_NAME WHERE created_at BETWEEN '2023-12-01' AND '2023-12-31' ORDER BY RAND() LIMIT 100 -- 依次添加后续每个月的查询语句
这种方式需要手动写每个月的日期范围,适合月份较少的场景。
最后提醒:记得把YOUR_TABLE_NAME替换成你的实际表名,起始日期根据实际年份调整(比如今年是2024年,去年11月就是2023-11-01),如果要包含到当前月,可以用数据库的日期函数动态计算去年11月的起始时间(比如MySQL用DATE_SUB(CURDATE(), INTERVAL 13 MONTH))。
内容的提问来源于stack exchange,提问作者Isa
相关产品推荐
相关产品推荐

