Để lọc các bản ghi có cột ngày tháng nằm trong một khoảng thời gian, MySQL sử dụng toán tử BETWEEN trong mệnh đề WHERE. Cú pháp: WHERE date_col BETWEEN 'start_date' AND 'end_date'. Điều này bao gồm cả ngày bắt đầu và ngày kết thúc.
Ví dụ minh họa
Tạo bảng chương trình khuyến mãi:
mysql> CREATE TABLE DemoTable1456 (
CustomerName VARCHAR(30),
StartOfferDate DATE,
EndOfferDate DATE
);
Chèn dữ liệu:
mysql> INSERT INTO DemoTable1456 VALUES ('Chris', '2019-09-01', '2019-09-30');
mysql> INSERT INTO DemoTable1456 VALUES ('David', '2019-09-01', '2019-10-30');
mysql> INSERT INTO DemoTable1456 VALUES ('Bob', '2018-10-01', '2018-10-20');
Dữ liệu:
mysql> SELECT * FROM DemoTable1456;
+--------------+----------------+--------------+ | CustomerName | StartOfferDate | EndOfferDate | +--------------+----------------+--------------+ | Chris | 2019-09-01 | 2019-09-30 | | David | 2019-09-01 | 2019-10-30 | | Bob | 2018-10-01 | 2018-10-20 | +--------------+----------------+--------------+
Tìm khách hàng có ưu đãi đang diễn ra hôm nay
mysql> SELECT * FROM DemoTable1456
WHERE DATE(NOW()) BETWEEN StartOfferDate AND EndOfferDate;
Kết quả (giả sử hôm nay 2019-10-05):
+--------------+----------------+--------------+ | CustomerName | StartOfferDate | EndOfferDate | +--------------+----------------+--------------+ | David | 2019-09-01 | 2019-10-30 | +--------------+----------------+--------------+
Giải thích
DATE(NOW()): Lấy phần ngày của thời gian hiện tại (bỏ giờ).BETWEEN A AND B: Tương đương>= A AND <= B.- So sánh kiểu DATE với DATE — chính xác, không lo phần giờ.
⚠️ Cảnh báo khi cột là DATETIME
Nếu cột là DATETIME, BETWEEN '2019-10-01' AND '2019-10-31' chỉ khớp đến '2019-10-31 00:00:00' (sáng sớm).
An toàn hơn:
WHERE PurchaseDate >= '2019-10-01' AND PurchaseDate < '2019-11-01' -- Ngày đầu tháng sau
Các biến thể hữu ích
| Mục đích | Cú pháp |
|---|---|
| 7 ngày qua | WHERE DateCol >= DATE_SUB(CURDATE(), INTERVAL 7 DAY) |
| Tháng hiện tại | WHERE DateCol >= DATE_FORMAT(CURDATE(), '%Y-%m-01') AND DateCol < DATE_FORMAT(CURDATE() + INTERVAL 1 MONTH, '%Y-%m-01') |
| Năm hiện tại | WHERE YEAR(DateCol) = YEAR(CURDATE()) |
| Tuần hiện tại (Thứ 2 - CN) | WHERE DateCol BETWEEN DATE_SUB(CURDATE(), INTERVAL WEEKDAY(CURDATE()) DAY) AND DATE_ADD(CURDATE(), INTERVAL (6 - WEEKDAY(CURDATE())) DAY) |
Hiệu năng
- Nên tạo index trên cột ngày tháng để truy vấn BETWEEN nhanh.
- Tránh dùng hàm trên cột index:
WHERE DATE(CreatedAt) BETWEEN ...→ mất index. Hãy viết range trực tiếp trên cột.