Khi cột ngày được lưu sebagai VARCHAR (ví dụ: '6/28/2011 9:58 AM'), cần chuyển đổi sang DATE trước khi dùng BETWEEN.
Cú pháp
SELECT * FROM ten_bang
WHERE STR_TO_DATE(LEFT(ten_cot, LOCATE(' ', ten_cot)), '%m/%d/%Y')
BETWEEN 'ngay_bat_dau' AND 'ngay_ket_thuc';
Ví dụ minh họa
Tạo bảng:
mysql> CREATE TABLE SearchDateAsVarchar (
-> Id INT NOT NULL AUTO_INCREMENT,
-> ShippingDate VARCHAR(100),
-> PRIMARY KEY(Id)
-> );
Chèn dữ liệu (định dạng MM/DD/YYYY HH:MM AM/PM):
mysql> INSERT INTO SearchDateAsVarchar(ShippingDate) VALUES('6/28/2011 9:58 AM');
mysql> INSERT INTO SearchDateAsVarchar(ShippingDate) VALUES('6/18/2011 10:50:39 AM');
mysql> INSERT INTO SearchDateAsVarchar(ShippingDate) VALUES('6/22/2011 11:45:40 AM');
Dữ liệu:
+----+-----------------------+ | Id | ShippingDate | +----+-----------------------+ | 1 | 6/28/2011 9:58 AM | | 2 | 6/18/2011 10:50:39 AM | | 3 | 6/22/2011 11:45:40 AM | +----+-----------------------+
Tìm kiếm từ 2011-06-20 đến 2011-06-28:
mysql> SELECT * FROM SearchDateAsVarchar
-> WHERE STR_TO_DATE(LEFT(ShippingDate, LOCATE(' ', ShippingDate)), '%m/%d/%Y')
-> BETWEEN '2011-06-20' AND '2011-06-28';
Kết quả:
+----+-----------------------+ | Id | ShippingDate | +----+-----------------------+ | 1 | 6/28/2011 9:58 AM | | 3 | 6/22/2011 11:45:40 AM | +----+-----------------------+
Giải thích hàm
LOCATE(' ', ShippingDate): Tìm vị trí dấu cách đầu tiên (tách ngày/giờ)LEFT(..., pos): Lấy phần ngày (MM/DD/YYYY)STR_TO_DATE(..., '%m/%d/%Y'): Parse chuỗi thành DATEBETWEEN ... AND ...: So sánh khoảng ngày
⚠️ Khuyến cáo quan trọng
Nên lưu ngày bằng kiểu DATE/DATETIME/TIMESTAMP thay vì VARCHAR để:
- Hiệu suất truy vấn tốt hơn (có index)
- Tránh lỗi parse dữ liệu bẩn
- Tận dụng hàm ngày tháng tự nhiên
- Tiết kiệm dung lượng lưu trữ