Tìm giá trị MAX từ cột VARCHAR chứa số trong MySQL
Cột VARCHAR so sánh theo thứ tự từ điển (lexicographic), '9' > '1000'. Cần CAST(... AS UNSIGNED) để so sánh theo giá trị số.
Ví dụ
Tạo bảng:
mysql> CREATE TABLE findMaxValueInVarcharField (
-> Id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
-> Value VARCHAR(200)
-> );
Chèn dữ liệu:
mysql> INSERT INTO findMaxValueInVarcharField(Value) VALUES
('200'), ('1000'), ('899474'), ('39474'), ('4958');
Dữ liệu:
+----+--------+ | Id | Value | +----+--------+ | 1 | 200 | | 2 | 1000 | | 3 | 899474 | | 4 | 39474 | | 5 | 4958 | +----+--------+
Tìm MAX theo giá trị số:
mysql> SELECT MAX(CAST(Value AS UNSIGNED)) AS MaximumValueFromVarcharField FROM findMaxValueInVarcharField;
Kết quả:
+------------------------------+ | MaximumValueFromVarcharField | +------------------------------+ | 899474 | +------------------------------+
So sánh không CAST (sai)
mysql> SELECT MAX(Value) FROM findMaxValueInVarcharField; +-----------+ | MAX(Value) | +-----------+ | 999999 | -- Sai! So sánh chuỗi: '9' > '1' > '8'... +-----------+
Các kiểu CAST cho số
CAST(col AS UNSIGNED): Số nguyên không dấu (0 đến 2^64-1)CAST(col AS SIGNED): Số nguyên có dấu (-2^63 đến 2^63-1)CAST(col AS DECIMAL(20,2)): Số thập phân cố định
Tối ưu hóa cho bảng lớn
- Generated Column (MySQL 5.7+):
ALTER TABLE t ADD value_num BIGINT AS (CAST(Value AS UNSIGNED)) STORED; CREATE INDEX idx_value_num ON t(value_num); SELECT MAX(value_num) FROM t;
- Functional Index (MySQL 8.0.13+):
CREATE INDEX idx_value_cast ON t((CAST(Value AS UNSIGNED)));
- Đổi kiểu cột: ALTER TABLE ... MODIFY Value BIGINT (nếu dữ liệu cho phép)
Lưu ý
- CAST trong WHERE/ORDER BY/GROUP BY làm mất index trên cột VARCHAR gốc
- Giá trị không phải số (abc) → CAST thành 0
- NULL → CAST thành NULL