MySQL如何实现同一列分组聚合且分组随机排序?
解决分组随机排序的问题
刚好遇到过类似的需求,我来给你说个靠谱的解法!你的核心需求是两个:把相同service_id的行聚在一起,同时分组之间的顺序每次查询都随机变化,之前的方法之所以不行,是因为没抓住这两个点的结合逻辑。
为什么之前的尝试没效果?
ORDER BY service_id ASC/DESC:只能按固定顺序排列分组,完全做不到随机ORDER BY RAND(service_id):用service_id作为随机种子,每个service_id对应的随机值是固定的,所以分组顺序永远不会变,自然满足不了随机的要求
正确的SQL写法(以MySQL为例)
我们可以先给每个不同的service_id生成一个每次查询都不一样的随机排序值,再用这个值来控制分组的顺序,同时保证同组的行聚在一起:
SELECT t.id, t.service_id FROM sample_table t JOIN ( -- 给每个service_id生成一个随机排序值 SELECT service_id, RAND() AS group_random FROM sample_table GROUP BY service_id ) AS group_order ON t.service_id = group_order.service_id -- 先按随机值排分组顺序,再按service_id确保同组聚在一起 ORDER BY group_order.group_random, t.service_id;
逻辑解释
- 子查询
group_order会对每个唯一的service_id生成一个全新的随机数(每次执行查询都会重新生成) - 主查询把原表和这个子查询关联,这样每一行都能拿到自己所属分组的随机排序值
- 排序时先按
group_random(分组的随机顺序),再按service_id(保证同一分组的行挨在一起)
支持窗口函数的数据库(比如MySQL 8.0+、PostgreSQL)
如果你的数据库支持窗口函数,还可以用更简洁的写法:
SELECT id, service_id FROM ( SELECT id, service_id, -- 给每个service_id分组分配一个统一的随机值 FIRST_VALUE(RAND()) OVER (PARTITION BY service_id) AS group_order FROM sample_table ) AS t ORDER BY group_order, service_id;
这样每次查询时,每个service_id分组都会得到一个随机的排序值,分组顺序就会随机变化,同时相同service_id的行始终聚在一起。
内容的提问来源于stack exchange,提问作者Tech Kid
相关产品推荐
相关产品推荐

