Sử dụng CAST() hoặc CONVERT() bên trong MAX() để so sánh theo giá trị số thay vì chuỗi.
Tạo bảng cột VARCHAR chứa số
mysql> CREATE TABLE DemoTable (UserMarks VARCHAR(20));
Chèn dữ liệu
mysql> INSERT INTO DemoTable VALUES('77'), ('98'), ('45'), ('56'), ('89'), ('99'), ('91'), ('94');
Xem dữ liệu (sắp xếp chuỗi: '99' > '98' > '94'... nhưng '100' < '99' theo chuỗi!)
mysql> SELECT * FROM DemoTable;
+-----------+ | UserMarks | +-----------+ | 77 | | 98 | | 45 | | 56 | | 89 | | 99 | | 91 | | 94 | +-----------+
MAX theo giá trị số (CAST sang SIGNED)
mysql> SELECT MAX(CAST(UserMarks AS SIGNED)) AS MAX_VALUE FROM DemoTable;
+-----------+ | MAX_VALUE | +-----------+ | 99 | +-----------+
Vấn đề so sánh chuỗi vs số
| Giá trị | Sắp xếp chuỗi (lexicographic) | Sắp xếp số (numeric) |
|---|---|---|
| '100' | 1 (đầu) | 100 (cuối) |
| '99' | 9 (cuối) | 99 |
| '9' | 9 | 9 |
Chuỗi so sánh từng ký tự: '1' < '9' → '100' < '99'. Cần CAST để so sánh đúng số học.
Các cách CAST
CAST(UserMarks AS SIGNED) -- Có dấu CAST(UserMarks AS UNSIGNED) -- Không dấu (cho ID, số lượng) CONVERT(UserMarks, SIGNED) -- Chuẩn SQL UserMarks + 0 -- Ép kiểu ngầm (MySQL shortcut)
Tìm cả MIN theo số
SELECT
MIN(CAST(UserMarks AS UNSIGNED)) AS Min_Value,
MAX(CAST(UserMarks AS UNSIGNED)) AS Max_Value
FROM DemoTable;
Cảnh báo
- Giá trị không phải số ('abc') → CAST thành 0 (hoặc NULL tùy mode)
- Nên validate dữ liệu trước:
WHERE UserMarks REGEXP '^[0-9]+$' - Index trên VARCHAR không dùng cho range query số sau CAST — cân nhắc đổi kiểu cột