วิธีง่ายที่สุด: ORDER BY DESC LIMIT 1 OFFSET 1
เรียงจากมากไปน้อย ข้าม 1 แถวแรก (Max) แล้ว取 1 แถวถัดไป
ตัวอย่างการใช้งาน
1. สร้างตาราง
mysql> CREATE TABLE DemoTable (
-> Value INT
-> );
Query OK, 0 rows affected (0.92 sec)
2. เพิ่มข้อมูล
mysql> INSERT INTO DemoTable VALUES(1), (2), (4), (204), (5); Query OK, 5 rows affected (...)
3. แสดงข้อมูลทั้งหมด
mysql> SELECT * FROM DemoTable;
ผลลัพธ์:
+-------+ | Value | +-------+ | 1 | | 2 | | 4 | | 204 | | 5 | +-------+ 5 rows in set (0.00 sec)
4. หาค่าที่ 2 สูงสุด
mysql> SELECT * FROM DemoTable ORDER BY Value DESC LIMIT 1 OFFSET 1;
ผลลัพธ์:
+-------+ | Value | +-------+ | 5 | +-------+ 1 row in set (0.00 sec)
วิธีอื่นๆ
1. ใช้ Subquery (Standard SQL)
SELECT MAX(Value) FROM DemoTable WHERE Value < (SELECT MAX(Value) FROM DemoTable);
2. ใช้ DISTINCT + LIMIT (จัดการ Duplicate Max)
SELECT DISTINCT Value FROM DemoTable ORDER BY Value DESC LIMIT 1 OFFSET 1;
3. ใช้ Window Function (MySQL 8.0+) - แนะนำ
SELECT Value FROM (
SELECT Value, ROW_NUMBER() OVER (ORDER BY Value DESC) AS rn
FROM DemoTable
) t WHERE rn = 2;
4. ใช้ Variable (MySQL 5.7 และเก่า)
SET @rownum = 0;
SELECT Value FROM (
SELECT Value, @rownum := @rownum + 1 AS rn
FROM DemoTable ORDER BY Value DESC
) t WHERE rn = 2;
เปรียบเทียบวิธีต่างๆ
| วิธี | Duplicate Max | Performance | MySQL Version |
|---|---|---|---|
| LIMIT 1 OFFSET 1 | ถือว่า Duplicate = แยกกัน | ดี (Index Scan) | All |
| DISTINCT + LIMIT | รวม Duplicate | ปานกลาง | All |
| Subquery MAX | รวม Duplicate | ดี (2 Index Scan) | All |
| ROW_NUMBER() | ควบคุมได้ (ROW_NUMBER vs RANK) | ดีมาก | 8.0+ |
Nth Highest (ทั่วไป)
-- Nth Highest (Distinct) SELECT DISTINCT Value FROM DemoTable ORDER BY Value DESC LIMIT 1 OFFSET (N-1); -- Nth Highest (With Duplicates) SELECT Value FROM DemoTable ORDER BY Value DESC LIMIT 1 OFFSET (N-1);
กรณีการใช้งานจริง
- Runner-up: อันดับ 2 ในการแข่งขัน
- Salary: เงินเดือนอันดับ 2 สูงสุด
- Sales: สินค้าขายได้อันดับ 2
- Benchmark: เวลาที่ 2 เร็วที่สุด