Sắp xếp VARCHAR chứa chữ và số theo thứ tự số học trong MySQL
Khi cột VARCHAR chứa cả số và chữ, sắp xếp mặc định (lexicographic) sẽ cho '100' < '190' < '20' < 'John'. Để sắp xếp số theo giá trị số học, dùng CAST() kết hợp IF() trong ORDER BY.
Ví dụ minh họa
Tạo bảng DemoTable:
mysql> CREATE TABLE DemoTable (EmployeeCode VARCHAR(100)); Query OK, 0 rows affected (1.17 sec)
Chèn dữ liệu:
mysql> INSERT INTO DemoTable VALUES('190');
Query OK, 1 row affected (0.14 sec)
mysql> INSERT INTO DemoTable VALUES('100');
Query OK, 1 row affected (0.30 sec)
mysql> INSERT INTO DemoTable VALUES('John');
Query OK, 1 row affected (0.23 sec)
mysql> INSERT INTO DemoTable VALUES('120');
Query OK, 1 row affected (0.21 sec)
Xem dữ liệu gốc:
mysql> SELECT * FROM DemoTable;
+--------------+ | EmployeeCode | +--------------+ | 190 | | 100 | | John | | 120 | +--------------+ 4 rows in set (0.00 sec)
Sắp xếp: số trước (theo giá trị số), chữ sau:
mysql> SELECT * FROM DemoTable ORDER BY IF(CAST(EmployeeCode AS SIGNED) = 0, 100000000000, CAST(EmployeeCode AS SIGNED));
Kết quả:
+--------------+ | EmployeeCode | +--------------+ | 100 | | 120 | | 190 | | John | +--------------+ 4 rows in set, 1 warning (0.00 sec)
Giải thích logic
CAST(EmployeeCode AS SIGNED): Ép kiểu sang số nguyên. Với 'John' → trả về 0IF(... = 0, 100000000000, ...): Nếu ép kiểu ra 0 (tức là không phải số) → gán giá trị rất lớn (đẩy xuống cuối)- Số hợp lệ giữ nguyên giá trị → được sắp xếp đúng thứ tự số học
Cách tiếp cận hiện đại hơn (MySQL 8.0+)
-- Sử dụng REGEXP để tách số và chữ
SELECT * FROM DemoTable
ORDER BY
CASE
WHEN EmployeeCode REGEXP '^[0-9]+$' THEN 0 ELSE 1 END, -- Số trước, chữ sau
CAST(EmployeeCode AS UNSIGNED); -- Sắp xếp số học
Lưu ý
- Cảnh báo (
1 warning) xuất hiện doCAST('John' AS SIGNED)trả về 0 với warning "Truncated incorrect INTEGER value" - Cách dùng
REGEXPsạch hơn và không gây warning - Nếu cần chữ trước, số sau: đổi thứ tự CASE (1 cho số, 0 cho chữ)