Giải pháp: DATE_SUB() với INTERVAL
Hàm DATE_SUB(date, INTERVAL expr unit) trừ interval từ ngày.
Ví dụ minh họa
Tạo bảng
mysql> CREATE TABLE DemoTable (
Id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
ArrivalDate DATETIME
);
Giả sử ngày hiện tại: 2019-06-08
Chèn dữ liệu
mysql> INSERT INTO DemoTable(ArrivalDate) VALUES('2019-05-15');
mysql> INSERT INTO DemoTable(ArrivalDate) VALUES('2019-06-08');
mysql> INSERT INTO DemoTable(ArrivalDate) VALUES('2019-05-20');
mysql> INSERT INTO DemoTable(ArrivalDate) VALUES('2019-05-12');
Dữ liệu gốc
+----+---------------------+ | Id | ArrivalDate | +----+---------------------+ | 1 | 2019-05-15 00:00:00 | | 2 | 2019-06-08 00:00:00 | | 3 | 2019-05-20 00:00:00 | | 4 | 2019-05-12 00:00:00 | +----+---------------------+
Truy vấn: Ngày >= hôm nay - 3 tuần
mysql> SELECT ArrivalDate FROM DemoTable
-> WHERE ArrivalDate >= DATE_SUB(CURDATE(), INTERVAL 3 WEEK);
Kết quả (>= 2019-05-18)
+---------------------+ | ArrivalDate | +---------------------+ | 2019-06-08 00:00:00 | | 2019-05-20 00:00:00 | +---------------------+
Các cách viết tương đương
| Cú pháp | Giải thích |
|---|---|
DATE_SUB(CURDATE(), INTERVAL 3 WEEK) | Hàm chuẩn |
CURDATE() - INTERVAL 3 WEEK | Toán tử - (MySQL extension) |
DATE_ADD(CURDATE(), INTERVAL -3 WEEK) | DATE_ADD với âm |
SUBDATE(CURDATE(), 21) | SUBDATE(date, days) - chỉ trừ ngày |
⚠️ Hiệu năng: Tránh hàm trên cột
-- ❌ Chậm WHERE DATE(ArrivalDate) >= DATE_SUB(CURDATE(), INTERVAL 3 WEEK) -- ✅ Nhanh (dùng index ArrivalDate) WHERE ArrivalDate >= DATE_SUB(CURDATE(), INTERVAL 3 WEEK) -- ✅ Nhanh nhất cho DATE column WHERE ArrivalDate >= CURDATE() - INTERVAL 21 DAY
Mở rộng: Các khoảng thời gian phổ biến
-- 7 ngày qua WHERE ArrivalDate >= CURDATE() - INTERVAL 7 DAY -- 30 ngày qua WHERE ArrivalDate >= CURDATE() - INTERVAL 30 DAY -- Tháng này WHERE ArrivalDate >= DATE_FORMAT(CURDATE(), '%Y-%m-01') AND ArrivalDate < DATE_FORMAT(CURDATE() + INTERVAL 1 MONTH, '%Y-%m-01') -- Quý này WHERE QUARTER(ArrivalDate) = QUARTER(CURDATE()) AND YEAR(ArrivalDate) = YEAR(CURDATE())
Lưu ý CURDATE() vs NOW()
CURDATE(): Chỉ ngày (DATE) - phù hợp so sánh với DATE columnNOW(): Ngày + giờ (DATETIME) - phù hợp so sánh với DATETIME/TIMESTAMP column- Khi so sánh DATE column với NOW(): MySQL tự cast NOW() → DATE