
在常规的 MySQL 查询中,结果默认按主键或指定字段排序,但有时业务需要"按我给的顺序来排"。比如首页要展示人工挑选的几条文章,或者后台要把某几个 ID 置顶,这时用 ORDER BY id DESC 显然无法满足。本文介绍一个用 ORDER BY INSTR 按指定 ID 顺序排序的实用技巧。
一、需求场景
1. 为什么需要自定义排序
最常见的情况是运营希望手动控制展示顺序。例如首页推荐位挑出了 14、16、17 三篇文章,希望它们严格按照这个顺序排列,而不是按 ID 大小或发布时间。这时普通的排序条件无能为力,必须让 SQL 感知到一个"顺序表"。
2. 常见误区
很多人第一反应是写 ORDER BY id IN (14,16,17),但这只会把命中的排在前面,内部顺序仍然由主键决定,无法实现指定排列。也有用 FIELD() 函数的做法,取值可以,但依赖的写法较长。
二、INSTR 排序实现
1. 核心写法
思路是把 ID 列表拼成一个字符串,再用 INSTR 找每个 ID 在该字符串中的位置,位置越靠前排序越靠前:
SELECT * FROM `jz_article`
WHERE id IN (14,16,17)
ORDER BY INSTR('14,16,17', CONCAT(',', id, ','))
这里用 CONCAT(',', id, ',') 给 ID 前后补上逗号,避免出现"1"匹配到"14"这类误判,是保证准确性的关键一步。
2. 结果说明
执行后结果会严格按 14、16、17 的顺序返回。如果 ID 列表变长,只需同步修改 IN 条件和 INSTR 的第一个参数即可,写法保持一致。
三、更健壮的替代方案
1. 使用 FIELD 函数
MySQL 内置的 FIELD() 更直观,它直接返回某个值在列表中的位置:
SELECT * FROM `jz_article`
WHERE id IN (14,16,17)
ORDER BY FIELD(id, 14, 16, 17)
这种写法可读性更好,也不存在字符串匹配的边界问题,是更推荐的做法。
2. 排序与筛选分离
如果 ID 列表很长,建议把它作为参数由程序动态拼接,同时对 ID 做整型校验,避免 SQL 注入风险。
关键配置提示
- INSTR 写法必须给 ID 前后补逗号,否则会出现 1 匹配 14 的错误
- FIELD 函数可读性更好,是同类需求的首选写法
- ID 列表来自前端时必须做整型过滤,防止 SQL 注入

快来评论,快来抢沙发吧~