Giới thiệu
Khi cột kiểu VARCHAR chứa số, sắp xếp mặc định theo thứ tự từ điển (lexicographic): '100' < '20' < '9'. Cần sắp xếp theo giá trị số thực.
1. Tạo bảng và dữ liệu
mysql> create table DemoTable (
-> Price varchar(20)
-> );
Query OK, 0 rows affected (0.92 sec)
mysql> insert into DemoTable values('80');
Query OK, 1 row affected (0.12 sec)
mysql> insert into DemoTable values('800');
Query OK, 1 row affected (0.16 sec)
mysql> insert into DemoTable values('108');
Query OK, 1 row affected (0.50 sec)
mysql> insert into DemoTable values('765');
Query OK, 1 row affected (0.14 sec)
2. Dữ liệu gốc
mysql> select *from DemoTable;
+-------+ | Price | +-------+ | 80 | | 800 | | 108 | | 765 | +-------+ 4 rows in set (0.00 sec)
3. Sắp xếp theo giá trị số giảm dần
mysql> select *from DemoTable
-> order by length(Price) DESC, Price DESC;
Logic:
LENGTH(Price) DESC: Số chữ số nhiều hơn = số lớn hơn (800, 765, 108 có 3 chữ số > 80 có 2 chữ số)Price DESC: Trong cùng độ dài, sắp xếp lexicographic = numeric (vì cùng độ dài, '800' > '765' > '108')
4. Kết quả
+-------+ | Price | +-------+ | 800 | | 765 | | 108 | | 80 | +-------+ 4 rows in set (0.00 sec)
Các cách khác:
ORDER BY CAST(Price AS UNSIGNED) DESC: Ép kiểu sang số (chuẩn, dễ hiểu, chậm hơn một chút)ORDER BY Price+0 DESC: Ép kiểu ngầm bằng phép toán (ngắn, nhanh)ORDER BY LPAD(Price, 20, '0') DESC: Pad 0 bên trái để so sánh chuỗi
Khuyên dùng: CAST(Price AS UNSIGNED) hoặc Price+0 cho rõ ràng và đúng mọi trường hợp (bao gồm số âm, thập phân nếu xử lý thêm).