按ID抽取随机样本(单ID对应多行)的SQL实现方法
按ID整组随机抽样的SQL实现
核心思路很简单:先抽ID,再关联拉全量明细,别直接对原表的行做随机抽样,不然很容易把同一个ID的记录拆碎,不符合要求。
通用适配写法(支持MySQL8.0+、PostgreSQL、Hive、Spark SQL、SQL Server 2017+等绝大多数主流SQL引擎)
WITH sampled_id AS ( -- 第一步:去重后随机抽100个ID SELECT DISTINCT ID FROM your_table -- 把这里替换成你的实际表名 ORDER BY RAND() LIMIT 100 ) -- 第二步:关联原表,取出抽中ID的所有行 SELECT t.* FROM your_table t JOIN sampled_id s ON t.ID = s.ID;
这个写法逻辑最直白,数据量在百万级以内跑起来完全没问题。
超大数据量优化写法(千万/亿级数据适用)
如果你的表总数据量特别大,ORDER BY RAND()会触发全表排序,性能很差,可以换随机过滤的方式减少排序开销:
WITH sampled_id AS ( SELECT DISTINCT ID FROM your_table -- 这里的过滤阈值自己调整:比如总共有20000个不重复ID,要抽100个,就填200/20000=0.01,多留一点冗余避免过滤后ID不够100 WHERE RAND() < 0.01 LIMIT 100 ) SELECT t.* FROM your_table t JOIN sampled_id s ON t.ID = s.ID;
特殊数据库适配调整
- Oracle:把
RAND()替换为DBMS_RANDOM.VALUE,LIMIT 100替换为FETCH FIRST 100 ROWS ONLY - SQL Server 2012及更早版本:把
LIMIT 100替换为TOP 100,随机排序可以用ORDER BY NEWID()替换ORDER BY RAND()
避坑提醒
不要直接写
SELECT * FROM your_table ORDER BY RAND() LIMIT 100,这个逻辑是随机抽100行数据,不是抽100个ID的全量数据,大概率会出现同一个ID只抽到部分行的情况,完全不符合你的抽样规则。
也不要直接对原表行加WHERE RAND() < 阈值的过滤条件,同样会漏掉抽中ID下的部分记录。
内容的提问来源于stack exchange,提问作者Azad
相关产品推荐
相关产品推荐

