需求:查詢結果中 name='lucy' 的記錄優先顯示,其餘按預設順序。
-- 原始數據 id | name 1 | lucy 2 | lily 3 | lucy 4 | lucy -- 期望結果 id | name 1 | lucy 3 | lucy 4 | lucy 2 | lily
FIND_IN_SET() + DESCSELECT * FROM test ORDER BY FIND_IN_SET(name, 'lucy') DESC;
FIND_IN_SET(str, strlist):返回 str 在逗號分隔的 strlist 中的位置(1-based),不存在返回 0lucy → 1,lily → 0,DESC 讓 1 排前面strlist 為常數字符串,不支援動態列表;含逗號的值會解析錯誤FIELD() 函數(推薦)SELECT * FROM test ORDER BY FIELD(name, 'lucy') DESC;
FIELD(str, str1, str2, ...):返回 str 在列表中的位置,不存在返回 0FIELD(status, 'urgent', 'high', 'normal', 'low')IN (...) 配合 FIELD() 保持指定順序方案 執行計劃特徵 效能評級 適用場景 ORDER BY FIELD()Using filesort⚠️ 中等 小結果集(<1萬行)、低頻查詢 ORDER BY FIND_IN_SET()Using filesort⚠️ 中等 同左,但不支援動態列表 UNION ALL分優先級查詢多次 ref/const掃描✅ 優 大表、高頻、有適當索引 應用層排序 無額外 DB 負載 ✅ 最優 結果集可在記憶體處理 優化建議
- 小表/低頻:直接用
ORDER BY FIELD(...),代碼簡潔- 大表/高頻:改用
UNION ALL分優先級查詢,每段走索引:(SELECT * FROM test WHERE name='lucy' ORDER BY id LIMIT 100) UNION ALL (SELECT * FROM test WHERE name!='lucy' ORDER BY id LIMIT 100)- 結果集 < 1000 行:應用層排序(Java
Comparator、Pythonsorted())最靈活- 避免在大表無索引列上使用
FIELD()排序,會觸發全表掃描 + filesort四、進階技巧:CASE WHEN 排序
SELECT * FROM test ORDER BY CASE WHEN name='lucy' THEN 1 WHEN name='lily' THEN 2 ELSE 3 END, id;
Using filesortFIELD(),語義清晰、無逗號陷阱LIMIT 使用時,FIELD() 排序會先全量排序再截取,效能陷阱Using filesort 即為排序無法走索引的信號