Vấn đề
Sắp xếp các ngày (DueDate) sao cho: các ngày **tương lai** (>= hôm nay) lên đầu, sắp tăng dần; các ngày **quá khứ** (< hôm nay) sau đó, cũng sắp tăng dần. Giống lịch nhắc nhở: sắp tới trước, đã qua sau.
Giải pháp: ORDER BY CASE
ORDER BY CASE WHEN DueDate >= CURDATE() THEN 0 ELSE 1 END, DueDate
Ví dụ minh họa
Giả sử hôm nay: 2019-07-22
Tạo bảng và chèn dữ liệu
mysql> CREATE TABLE DemoTable (DueDate DATE);
mysql> INSERT INTO DemoTable VALUES
('2019-03-10'), ('2019-08-25'), ('2019-06-01'), ('2019-12-31');
Truy vấn
mysql> SELECT * FROM DemoTable ORDER BY CASE WHEN DueDate >= CURDATE() THEN 0 ELSE 1 END, DueDate;
Kết quả (hôm nay 2019-07-22)
+------------+ | DueDate | +------------+ | 2019-08-25 | -- Tương lai, gần nhất trước | 2019-12-31 | -- Tương lai | 2019-03-10 | -- Quá khứ, cũ nhất trước | 2019-06-01 | -- Quá khứ +------------+
Giải thích
CASE WHEN DueDate >= CURDATE() THEN 0 ELSE 1 END: Nhóm tương lai = 0, quá khứ = 1.ORDER BY nhóm, DueDate: Sắp theo nhóm trước, rồi theo ngày trong nhóm.- Kết quả: Tương lai tăng dần (gần nhất đầu), quá khứ tăng dần (cũ nhất đầu).
Biến thể: Quá khứ giảm dần (gần đây trước)
ORDER BY CASE WHEN DueDate >= CURDATE() THEN 0 ELSE 1 END,
CASE WHEN DueDate >= CURDATE() THEN DueDate END ASC,
CASE WHEN DueDate < CURDATE() THEN DueDate END DESC
Lưu ý
CURDATE()trả về ngày hiện tại của server (timezone server).- Nếu cột DATETIME, dùng
DATE(DueDate) >= CURDATE()hoặc so sánh trực tiếpDueDate >= NOW(). - Index trên DueDate vẫn có thể dùng cho phần sắp xếp thứ 2 (trong mỗi nhóm).