สถานการณ์
ต้องการ 3 แถวที่เพิ่มล่าสุด (Id สูงสุด 3 ค่า) แต่แสดงผลเรียงจากน้อยไปมาก (Ascending)
วิธีแก้: Subquery + ORDER BY DESC LIMIT + Outer ORDER BY ASC
SELECT * FROM (
SELECT * FROM table_name ORDER BY id_column DESC LIMIT 3
) AS alias ORDER BY id_column ASC;
ตัวอย่างการใช้งาน
1. สร้างตาราง
mysql> CREATE TABLE DemoTable1579 (
-> Id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
-> Name VARCHAR(20)
-> );
Query OK, 0 rows affected (0.67 sec)
2. เพิ่มข้อมูล
mysql> INSERT INTO DemoTable1579(Name) VALUES('Robert'), ('Bob'), ('Chris'), ('Sam'), ('Mike');
Query OK, 5 rows affected (...)
3. แสดงข้อมูลทั้งหมด
mysql> SELECT * FROM DemoTable1579;
ผลลัพธ์:
+----+--------+ | Id | Name | +----+--------+ | 1 | Robert | | 2 | Bob | | 3 | Chris | | 4 | Sam | | 5 | Mike | +----+--------+ 5 rows in set (0.00 sec)
4. 3 แถวล่าสุด เรียง Ascending
mysql> SELECT * FROM (
-> SELECT * FROM DemoTable1579 ORDER BY Id DESC LIMIT 3
-> ) t ORDER BY Id;
ผลลัพธ์ (Id 3,4,5 เรียงน้อยไปมาก):
+----+-------+ | Id | Name | +----+-------+ | 3 | Chris | | 4 | Sam | | 5 | Mike | +----+-------+ 3 rows in set (0.00 sec)
อธิบาย Logic
- Inner Query:
ORDER BY Id DESC LIMIT 3→ หา 3 แถว Id สูงสุด (5,4,3) - Outer Query:
ORDER BY Id ASC→ เรียง 3 แถวนั้นจากน้อยไปมาก (3,4,5)
วิธีอื่นๆ (MySQL 8.0+)
Window Function
SELECT Id, Name FROM (
SELECT Id, Name, ROW_NUMBER() OVER (ORDER BY Id DESC) AS rn
FROM DemoTable1579
) t WHERE rn <= 3 ORDER BY Id ASC;
CTE (Common Table Expression)
WITH Latest3 AS (
SELECT * FROM DemoTable1579 ORDER BY Id DESC LIMIT 3
)
SELECT * FROM Latest3 ORDER BY Id ASC;
Performance
- Inner Query ใช้ Index Scan Backward + Limit → เร็วมาก
- Outer Query สั่งจับ 3 แถว → เล็กมาก
- Derived Table (Subquery ใน FROM) ใน MySQL 5.7+ ใช้ Materialization / Merge Optimization
กรณีการใช้งานจริง
- Chat App: โหลดข้อความล่าสุด 30 ข้อความ แล้วแสดงเก่าไปใหม่
- Notification: 5 รายการล่าสุด เรียงตามเวลา
- Log Viewer: Error ล่าสุด 100 รายการ เรียงเวลา
- Dashboard: Top 10 Sales วันนี้ เรียงตามยอดขาย