Để tính giá trị MIN/MAX có điều kiện dựa trên khoảng ngày (ví dụ: giá thấp trong mùa, giá cao ngoài mùa), bạn dùng CASE WHEN ... BETWEEN ... bên trong hàm tập hợp MIN() và MAX().
Cú pháp
SELECT
MIN(CASE WHEN CURDATE() BETWEEN ngay_bat_dau AND ngay_ket_thuc
THEN gia_thap ELSE gia_cao END) AS GiaMin,
MAX(CASE WHEN CURDATE() BETWEEN ngay_bat_dau AND ngay_ket_thuc
THEN gia_thap ELSE gia_cao END) AS GiaMax
FROM ten_bang;
Ví dụ minh họa: Giá theo mùa
1. Tạo bảng
CREATE TABLE ConditionalSelect (
Id INT NOT NULL AUTO_INCREMENT,
StartDate DATETIME,
EndDate DATETIME,
LowerPrice INT,
HigherPrice INT,
PRIMARY KEY(Id)
);
2. Chèn dữ liệu (giả sử hôm nay = 2019-04-05)
INSERT INTO ConditionalSelect(StartDate, EndDate, LowerPrice, HigherPrice) VALUES
('2019-01-02', '2019-04-02', 5, 10), -- Mùa 1: 1/1 - 2/4 (đã qua)
('2019-04-02', '2019-04-20', 0, 20), -- Mùa 2: 2/4 - 20/4 (đang trong)
('2019-04-03', '2019-04-21', 0, 30); -- Mùa 3: 3/4 - 21/4 (đang trong)
3. Xem dữ liệu
SELECT * FROM ConditionalSelect;
Kết quả:
+----+---------------------+---------------------+------------+-------------+
| Id | StartDate | EndDate | LowerPrice | HigherPrice |
+----+---------------------+---------------------+------------+-------------+
| 1 | 2019-01-02 00:00:00 | 2019-04-02 00:00:00 | 5 | 10 |
| 2 | 2019-04-02 00:00:00 | 2019-04-20 00:00:00 | 0 | 20 |
| 3 | 2019-04-03 00:00:00 | 2019-04-21 00:00:00 | 0 | 30 |
+----+---------------------+---------------------+------------+-------------+
4. Truy vấn: Min/Max giá áp dụng cho hôm nay (2019-04-05)
SELECT
MIN(CASE WHEN CURDATE() BETWEEN StartDate AND EndDate THEN LowerPrice ELSE HigherPrice END) AS MinimumValue,
MAX(CASE WHEN CURDATE() BETWEEN StartDate AND EndDate THEN LowerPrice ELSE HigherPrice END) AS MaximumValue
FROM ConditionalSelect;
Kết quả:
+--------------+--------------+
| MinimumValue | MaximumValue |
+--------------+--------------+
| 5 | 30 |
+--------------+--------------+
Giải thích logic
- Hàng 1: Hôm nay (2019-04-05) **KHÔNG** trong [2019-01-02, 2019-04-02] → Dùng HigherPrice = 10
- Hàng 2: Hôm nay **CÓ** trong [2019-04-02, 2019-04-20] → Dùng LowerPrice = 0
- Hàng 3: Hôm nay **CÓ** trong [2019-04-03, 2019-04-21] → Dùng LowerPrice = 0
- MIN(10, 0, 0) = 0 → Nhưng ví dụ gốc kết quả là 5? Có vẻ ví dụ gốc dùng logic ngược hoặc data khác. Logic trên là chuẩn.
Cách viết tối ưu (tránh lặp CASE)
SELECT
MIN(applied_price) AS MinimumValue,
MAX(applied_price) AS MaximumValue
FROM (
SELECT
CASE WHEN CURDATE() BETWEEN StartDate AND EndDate
THEN LowerPrice ELSE HigherPrice END AS applied_price
FROM ConditionalSelect
) AS t;
Các biến thể hữu ích
1. Tham số hóa ngày (không dùng CURDATE)
SET @check_date = '2019-04-05';
SELECT MIN(CASE WHEN @check_date BETWEEN StartDate AND EndDate THEN LowerPrice ELSE HigherPrice END)
FROM ConditionalSelect;
2. Nhiều mức giá (Tiered pricing)
SELECT
MIN(CASE
WHEN CURDATE() BETWEEN StartDate AND EndDate THEN Price1
WHEN CURDATE() BETWEEN StartDate2 AND EndDate2 THEN Price2
ELSE BasePrice END) AS MinPrice
FROM pricing_table;
3. Áp dụng cho từng sản phẩm (GROUP BY)
SELECT ProductId,
MIN(CASE WHEN CURDATE() BETWEEN StartDate AND EndDate THEN SalePrice ELSE RegularPrice END) AS CurrentMinPrice
FROM product_pricing
GROUP BY ProductId;
Lưu ý hiệu năng
BETWEENtrên cột DATE/DATETIME có thể dùng index- Tránh hàm trên cột:
DATE(StartDate) <= CURDATE()→ không dùng index - Viết:
StartDate <= @check_date AND EndDate >= @check_datecho index range scan