如何在MySQL中实现tbl_featured_professional表前40条按ranking其余按score排序?
这个需求我之前帮人处理过,刚好有两种靠谱的MySQL实现方式,看你的数据库版本来选就行:
方法1:用UNION ALL拆分查询(兼容所有MySQL版本)
如果你的MySQL是5.x这类不支持窗口函数的老版本,这种方法最合适。核心思路是先把按ranking排序的前40条取出来,再查询剩下的记录并按score排序,最后合并两个结果集。
SQL代码如下:
-- 第一步:取按ranking排序的前40条记录 SELECT id, user_id, ranking, score, createdDate FROM tbl_featured_professional ORDER BY ranking LIMIT 40 UNION ALL -- 第二步:取剩余记录,按score排序(排除前40条的id) SELECT id, user_id, ranking, score, createdDate FROM tbl_featured_professional WHERE id NOT IN ( SELECT id FROM tbl_featured_professional ORDER BY ranking LIMIT 40 ) ORDER BY score DESC; -- 这里可以根据需求改成ASC(升序)
⚠️ 注意:
- 用
UNION ALL而非UNION,因为UNION会自动去重,而我们已经确保两次查询的记录无重叠,UNION ALL性能更优。 - 子查询里的
LIMIT 40用来锁定前40条的id,避免重复获取。
方法2:用窗口函数ROW_NUMBER()(MySQL 8.0+推荐)
如果你的MySQL版本是8.0及以上,用窗口函数会更简洁高效,不需要拆分两次查询:
SELECT id, user_id, ranking, score, createdDate FROM ( SELECT *, -- 按ranking排序,给每条记录分配唯一行号 ROW_NUMBER() OVER (ORDER BY ranking) AS rn FROM tbl_featured_professional ) AS temp ORDER BY -- 前40条优先排在前面,其余往后放 CASE WHEN rn <= 40 THEN rn ELSE 999999 END, -- 前40条按ranking排序,其余按score排序 CASE WHEN rn <= 40 THEN ranking ELSE score END DESC; -- score排序方向按需调整
💡 解释:
- 内层子查询用
ROW_NUMBER()给每条记录按ranking排序生成行号rn。 - 外层的
ORDER BY通过两个CASE实现规则:先把行号≤40的记录排在最前面,剩下的放到后面;然后前40条按ranking排序,其余按score排序。 - 这里的
999999只要是一个比表中总行数大的数就行,确保剩余记录都排在后面。
额外提醒
因为你提到ranking是唯一字段,所以两种方法都不会出现重复或遗漏记录的问题。如果需要调整score的排序方向,直接把DESC改成ASC即可。
内容的提问来源于stack exchange,提问作者Jim Kasprowicz
相关产品推荐
相关产品推荐

