จัดเรียงผลลัพธ์ UNION ตามลำดับที่ต้องการด้วย CASE WHEN
คำสั่ง UNION จะจัดเรียงผลลัพธ์อัตโนมัติ (และลบแถวซ้ำ) ทำให้ลำดับเดิมของแต่ละ SELECT หายไป แก้ไขได้โดยใช้ ORDER BY CASE แทน UNION
ตัวอย่างสร้างตารางและข้อมูล
CREATE TABLE DemoTable (
Id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
ShippingDate DATETIME
);
INSERT INTO DemoTable (ShippingDate) VALUES
('2019-04-21'), ('2019-01-01'), ('2019-05-11'),
('2018-12-31'), ('2019-02-18');
ข้อมูลในตาราง
+----+---------------------+ | Id | ShippingDate | +----+---------------------+ | 1 | 2019-04-21 00:00:00 | | 2 | 2019-01-01 00:00:00 | | 3 | 2019-05-11 00:00:00 | | 4 | 2018-12-31 00:00:00 | | 5 | 2019-02-18 00:00:00 | +----+---------------------+
คำสั่งจัดเรียง: วันที่อนาคต (>= วันนี้) ก่อน เรียงจากใหม่ไปเก่า, วันที่ผ่านมา (< วันนี้) ทีหลัง เรียงจากใหม่ไปเก่า
SELECT * FROM DemoTable
ORDER BY CASE
WHEN ShippingDate < CURDATE() THEN ShippingDate
ELSE CURDATE()
END DESC, ShippingDate ASC;
ผลลัพธ์ (สมมติวันนี้คือ 2019-06-04)
+----+---------------------+ | Id | ShippingDate | +----+---------------------+ | 3 | 2019-05-11 00:00:00 | | 1 | 2019-04-21 00:00:00 | | 5 | 2019-02-18 00:00:00 | | 2 | 2019-01-01 00:00:00 | | 4 | 2018-12-31 00:00:00 | +----+---------------------+
คำอธิบาย:
CASE WHEN ShippingDate < CURDATE() THEN ShippingDate ELSE CURDATE() END: แยกเป็น 2 กลุ่ม: วันที่ผ่านมา (ค่า = วันที่จริง) และวันที่อนาคต (ค่า = วันนี้ = ค่าคงที่)DESC: เรียงค่า CASE จากมากไปน้อย → วันที่อนาคต (CURDATE()) จะมากกว่าวันที่ผ่านมา → กลุ่มอนาคตอยู่บนShippingDate ASC: จัดเรียงรองภายในกลุ่มเดียวกันจากเก่าไปใหม่
เทคนิคนี้เหมาะกับ: การแสดงรายการ "กำลังจะมาถึง" ก่อน แล้วค่อย "ที่ผ่านมาแล้ว" ทั้งในคิวรี่เดียว ไม่ต้อง UNION