Mệnh đề IN() trong MySQL **không bảo đảm thứ tự** kết quả theo danh sách giá trị. Để giữ thứ tự, dùng ORDER BY FIND_IN_SET().
Ví dụ minh họa
Tạo bảng sản phẩm:
mysql> CREATE TABLE ProductStock (
-> ProductId INT,
-> ProductName VARCHAR(20),
-> ProductQuantity INT,
-> ProductPrice FLOAT
-> );
mysql> INSERT INTO ProductStock VALUES(1, 'Product-101', 10, 500.56);
mysql> INSERT INTO ProductStock VALUES(25, 'Product-111', 5, 150.00);
mysql> INSERT INTO ProductStock VALUES(67, 'Product-311', 7, 1000.50);
mysql> INSERT INTO ProductStock VALUES(55, 'Product-561', 8, 900.00);
mysql> INSERT INTO ProductStock VALUES(75, 'Product-221', 15, 670.56);
Dữ liệu:
+-----------+-------------+-----------------+--------------+ | ProductId | ProductName | ProductQuantity | ProductPrice | +-----------+-------------+-----------------+--------------+ | 1 | Product-101 | 10 | 500.56 | | 25 | Product-111 | 5 | 150 | | 67 | Product-311 | 7 | 1000.5 | | 55 | Product-561 | 8 | 900 | | 75 | Product-221 | 15 | 670.56 | +-----------+-------------+-----------------+--------------+
Vấn đề: IN() sắp xếp theo ProductId mặc định
mysql> SELECT * FROM ProductStock WHERE ProductId IN (25,55,67,75,1);
Kết quả sẽ theo thứ tự 1, 25, 55, 67, 75 (sắp xếp số tăng).
Giải pháp: ORDER BY FIND_IN_SET()
mysql> SELECT * FROM ProductStock
-> WHERE ProductId IN (25,55,67,75,1)
-> ORDER BY FIND_IN_SET(ProductId, '25,55,67,75,1');
Kết quả theo đúng thứ tự mong muốn:
+-----------+-------------+-----------------+--------------+ | ProductId | ProductName | ProductQuantity | ProductPrice | +-----------+-------------+-----------------+--------------+ | 25 | Product-111 | 5 | 150 | | 55 | Product-561 | 8 | 900 | | 67 | Product-311 | 7 | 1000.5 | | 75 | Product-221 | 15 | 670.56 | | 1 | Product-101 | 10 | 500.56 | +-----------+-------------+-----------------+--------------+
Giải thích FIND_IN_SET
FIND_IN_SET(str, strlist): Trả về vị trí (1-based) của str trong chuỗi danh sách strlist- Danh sách phải không có khoảng trắng:
'25,55,67,75,1' - Trả về 0 nếu không tìm thấy (hàng không trong IN sẽ lên đầu nếu không có WHERE)
Lưu ý: FIND_IN_SET không dùng index, chậm trên bảng lớn. Với dữ liệu lớn, cân nhắc JOIN với bảng tạm hoặc derived table có cột sort_order.