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

Giữ thứ tự SELECT trong MySQL UNION với ORDER BY CASE?

Vấn đề

UNION mặc định loại bỏ duplicate và không bảo toàn thứ tự các SELECT con. Cần cách sắp xếp kết quả hợp nhất theo quy tắc tùy chỉnh.

Giải pháp: ORDER BY CASE thay vì UNION

Thay vì dùng UNION nhiều SELECT, dùng một SELECT duy nhất với ORDER BY CASE.

Ví dụ: Sắp xếp ngày giao hàng

Yêu cầu: Ngày tương lai trước (giảm dần), ngày quá khứ sau (giảm dần)

Tạo bảng và dữ liệu

mysql> CREATE TABLE DemoTable (
    Id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
    ShippingDate DATETIME
);

mysql> INSERT INTO DemoTable(ShippingDate) VALUES('2019-04-21');
mysql> INSERT INTO DemoTable(ShippingDate) VALUES('2019-01-01');
mysql> INSERT INTO DemoTable(ShippingDate) VALUES('2019-05-11');
mysql> INSERT INTO DemoTable(ShippingDate) VALUES('2018-12-31');
mysql> INSERT INTO DemoTable(ShippingDate) VALUES('2019-02-18');

Truy vấn với ORDER BY CASE

mysql> SELECT * FROM DemoTable 
    -> ORDER BY CASE 
        WHEN ShippingDate < CURDATE() THEN ShippingDate 
        ELSE CURDATE() 
    END DESC, 
    ShippingDate ASC;

Kết quả (giả sử CURDATE() = 2019-03-01)

+----+---------------------+
| Id | ShippingDate        |
+----+---------------------+
| 3  | 2019-05-11 00:00:00 |  -- Tương lai: mới nhất trước
| 1  | 2019-04-21 00:00:00 |
| 5  | 2019-02-18 00:00:00 |  -- Quá khứ: mới nhất trước
| 2  | 2019-01-01 00:00:00 |
| 4  | 2018-12-31 00:00:00 |
+----+---------------------+

Giải thích logic CASE

  • ShippingDate < CURDATE(): Ngày quá khứ → trả về chính ngày đó
  • ELSE CURDATE(): Ngày tương lai → trả về hôm nay (giá trị cố định)
  • ORDER BY ... DESC: Giá trị lớn hơn trước → CURDATE() (tương lai) lên đầu
  • ShippingDate ASC: Tie-breaker cho cùng nhóm

Mở rộng: Nhiều nhóm ưu tiên

ORDER BY CASE
    WHEN status = 'urgent' THEN 1
    WHEN status = 'high' THEN 2
    WHEN status = 'normal' THEN 3
    ELSE 4
END ASC,
created_at DESC;

Khi nào cần UNION?

  • Kết hợp kết quả từ nhiều bảng khác cấu trúc
  • Cần UNION ALL để giữ duplicate (nhanh hơn UNION)
  • Khi logic WHERE phức tạp khác nhau cho từng tập

Mẹo: Thường dùng ORDER BY FIELD(status, 'urgent','high','normal') cho đọc dễ hơn CASE.