Cách chuẩn: SELECT DISTINCT cot FROM bang ORDER BY cot DESC LIMIT (N-1), 1.
Cú pháp
SELECT DISTINCT ten_cot FROM ten_bang ORDER BY ten_cot DESC LIMIT (N-1), 1;
DISTINCT: Loại bỏ giá trị trùng (nếu muốn distinct Nth highest).LIMIT offset, count: Bỏ quaoffsethàng, lấycounthàng. Offset = N-1.
Ví dụ: Tìm giá trị lớn thứ 3 (N=3)
Tạo bảng:
CREATE TABLE DemoTable1594 (Marks INT); INSERT INTO DemoTable1594 VALUES (76), (95), (56), (96), (89);
Giá trị distinct DESC: 96, 95, 89, 76, 56.
Lớn thứ 3 = 89 (offset 2, limit 1):
SELECT DISTINCT Marks FROM DemoTable1594 ORDER BY Marks DESC LIMIT 2, 1;
Kết quả
| Marks |
|---|
| 89 |
Các trường hợp đặc biệt
1. Không dùng DISTINCT (lấy theo hàng, kể trùng)
SELECT Marks FROM DemoTable1594 ORDER BY Marks DESC LIMIT 2, 1;
2. MySQL 8.0+: Window Function
SELECT Marks FROM (
SELECT DISTINCT Marks, ROW_NUMBER() OVER (ORDER BY Marks DESC) AS rn
FROM DemoTable1594
) t WHERE rn = 3;
3. N lớn (pagination): Offset lớn chậm
Với N=100000, LIMIT 99999, 1 rất chậm. Cách tốt hơn:
-- Nếu có index trên Marks SELECT Marks FROM DemoTable1594 WHERE Marks < (SELECT Marks FROM DemoTable1594 ORDER BY Marks DESC LIMIT 99999, 1) ORDER BY Marks DESC LIMIT 1;
Hoặc dùng keyset pagination (cần cột unique).
So sánh cách làm
| Cách | Phiên bản | Hiệu năng | Xử lý tie |
|---|---|---|---|
| DISTINCT + LIMIT offset,1 | Tất cả | TB (filesort nếu không index) | Distinct values |
| ROW_NUMBER() OVER | 8.0+ | Tốt (có thể dùng index) | Linh hoạt |
| Subquery MAX lồng nhau | Tất cả | Kém (N lần subquery) | Distinct |