Vấn đề
Mệnh đề IN (...) không bảo vệ thứ tự kết quả. MySQL trả về theo thứ tự index/physical.
Giải pháp: FIND_IN_SET()
SELECT * FROM bang WHERE cot IN (val1, val2, val3) ORDER BY FIND_IN_SET(cot, 'val1,val2,val3');
Ví dụ: Sắp xếp Id theo thứ tự 100, 145, 103, 130
Dữ liệu (thứ tự vật lý: 100, 130, 103, 134, 102, 145)
+------+-------+ | Id | Name | +------+-------+ | 100 | John | | 130 | Carol | | 103 | Bob | | 134 | Sam | | 102 | Larry | | 145 | David | +------+-------+
Truy vấn có ORDER BY FIND_IN_SET
mysql> SELECT * FROM returnRecordSetOrderDemo
-> WHERE Id IN (100, 145, 103, 130)
-> ORDER BY FIND_IN_SET(Id, '100,145,103,130');
Kết quả (theo đúng thứ tự IN)
+------+-------+ | Id | Name | +------+-------+ | 100 | John | | 145 | David | | 103 | Bob | | 130 | Carol | +------+-------+
Cách hoạt động FIND_IN_SET
FIND_IN_SET(str, strlist): Trả về vị trí (1-based) của str trong strlist (phân cách bởi dấu phẩy)- Không tìm thấy → trả về 0
- NULL input → trả về NULL
Lưu ý hiệu năng
FIND_IN_SETkhông dùng được index → full table scan trên kết quả IN- Chỉ dùng cho tập kết quả nhỏ (hàng trăm dòng)
- Với tập lớn: JOIN với derived table/table variable có cột sort_order
Cách thay thế cho tập lớn
-- Tạo temp table/ordering table CREATE TEMPORARY TABLE sort_order (id INT PRIMARY KEY, sort_order INT); INSERT INTO sort_order VALUES (100,1), (145,2), (103,3), (130,4); SELECT b.* FROM bang b JOIN sort_order s ON b.id = s.id WHERE b.id IN (100,145,103,130) ORDER BY s.sort_order;