Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> MySQL

การหาวันที่ใกล้ที่สุดในอนาคตจากช่วงวันที่ใน MySQL

เมื่อต้องการหาวันที่ที่ใกล้ที่สุดในอนาคต (Next Closest Date) จากชุดวันที่ในตาราง โดยเปรียบเทียบกับวันที่/เวลาปัจจุบัน สามารถใช้ ORDER BY แบบเฉพาะเจาะจงพร้อม LIMIT 1

ตัวอย่างการใช้งาน

สร้างตารางวันที่จัดส่ง:

mysql> CREATE TABLE DemoTable1454 (ShippingDate DATE);

เพิ่มข้อมูล (มีทั้งอดีตและอนาคต):

mysql> INSERT INTO DemoTable1454 VALUES ('2019-10-01'), ('2019-10-03'), ('2019-10-05'), ('2019-10-04'), ('2018-10-06'), ('2019-10-06');

ดูข้อมูลและวันที่ปัจจุบัน:

mysql> SELECT * FROM DemoTable1454;
+--------------+
| ShippingDate |
+--------------+
| 2019-10-01   |
| 2019-10-03   |
| 2019-10-05   |
| 2019-10-04   |
| 2018-10-06   |
| 2019-10-06   |
+--------------+

mysql> SELECT NOW();
+---------------------+
| now()               |
+---------------------+
| 2019-10-04 21:30:01 |
+---------------------+

หาวันที่จัดส่งถัดไปที่ใกล้ที่สุด (หลังจาก NOW()):

mysql> SELECT * FROM DemoTable1454
    -> ORDER BY (ShippingDate > NOW()) DESC,
    ->         (CASE WHEN ShippingDate > NOW() THEN ShippingDate END),
    ->         ShippingDate DESC
    -> LIMIT 1;

ผลลัพธ์ (2019-10-05 คือวันที่ถัดไปหลัง 2019-10-04):

+--------------+
| ShippingDate |
+--------------+
| 2019-10-05   |
+--------------+

คำอธิบาย Logic การเรียง (ORDER BY)

  1. (ShippingDate > NOW()) DESC: ใส่วันที่ในอนาคต (TRUE=1) ไว้หน้า, อดีต (FALSE=0) ไว้ท้าย
  2. CASE WHEN ShippingDate > NOW() THEN ShippingDate END: เรียงวันที่ในอนาคตจากน้อยไปมาก (ASC implicit)
  3. ShippingDate DESC: Tie-breaker สำหรับวันที่ในอดีต (ไม่สำคัญเพราะ LIMIT 1)

วิธีง่ายกว่า (MySQL 8.0+ / MariaDB)

-- ใช้ WHERE กรองเฉพาะอนาคต แล้ว ORDER BY ASC LIMIT 1
SELECT * FROM DemoTable1454
WHERE ShippingDate > NOW()
ORDER BY ShippingDate ASC
LIMIT 1;

วิธีนี้อ่านง่ายกว่า ใช้ Index ได้ และประสิทธิภาพดีกว่า

กรณีต้องการ "วันที่ใกล้ที่สุด" ทั้งอดีตและอนาคต (Nearest Date)

SELECT * FROM DemoTable1454
ORDER BY ABS(DATEDIFF(ShippingDate, NOW()))
LIMIT 1;

ใช้ ABS(DATEDIFF(...)) หาความต่างวันแบบสัมบูรณ์ แล้วเรียงน้อยไปมาก