Giải pháp: FIELD() hoặc CASE
Hàm FIELD(value, val1, val2, ...) trả về vị trí (1-based) của value trong danh sách, hoặc 0 nếu không có. Dùng để sắp xếp tùy chỉnh.
Ví dụ minh họa
Tạo bảng và dữ liệu
mysql> CREATE TABLE DemoTable (Value INT); mysql> INSERT INTO DemoTable VALUES(10), (70), (60), (56), (81), (85);
Dữ liệu gốc
+-------+ | Value | +-------+ | 10 | | 70 | | 60 | | 56 | | 81 | | 85 | +-------+
Yêu cầu: 60, 70, 81 xếp trước (DESC), còn lại ASC
mysql> SELECT * FROM DemoTable
-> ORDER BY FIELD(Value, 60, 70, 81) DESC;
Kết quả
+-------+ | Value | +-------+ | 81 | <-- FIELD=3 (cao nhất) → DESC lên đầu | 70 | <-- FIELD=2 | 60 | <-- FIELD=1 | 10 | <-- FIELD=0 → cuối, ASC | 56 | | 85 | +-------+
Giải thích FIELD()
FIELD(60, 60,70,81) = 1FIELD(70, 60,70,81) = 2FIELD(81, 60,70,81) = 3FIELD(10, 60,70,81) = 0(không có trong list)DESC: 3, 2, 1, 0 → 81, 70, 60, (còn lại)
So sánh FIELD() vs CASE
| Phương pháp | Ví dụ | Ưu điểm |
|---|---|---|
| FIELD() | ORDER BY FIELD(col, 3,1,2) DESC | Ngắn gọn, đọc dễ, danh sách giá trị |
| CASE | ORDER BY CASE col WHEN 3 THEN 1 WHEN 1 THEN 2 ELSE 3 END | Linh hoạt điều kiện phức tạp |
| FIND_IN_SET | ORDER BY FIND_IN_SET(col, '3,1,2') DESC | Chuỗi CSV, nhưng chậm hơn |
Mở rộng: Sắp xếp phức tạp
-- Ưu tiên status, sau đó ngày
ORDER BY
FIELD(status, 'urgent', 'high', 'normal') DESC,
created_at ASC;
-- Custom order cho category
ORDER BY
CASE category
WHEN 'premium' THEN 1
WHEN 'standard' THEN 2
ELSE 3
END,
price DESC;
Lưu ý hiệu năng
- FIELD()/CASE không dùng index cho ORDER BY
- Bảng lớn: cân nhắc thêm cột
sort_order INTpre-computed - Hoặc dùng
ORDER BY (col IN (60,70,81)) DESC, col ASCcho boolean sort