Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> MySQL

Sắp xếp ngày theo ngày/tháng hiện tại trong MySQL (ORDER BY CASE)


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ếp DueDate >= 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).