Tìm Max và Second Max Salary dùng Subquery
Kỹ thuật: Subquery lồng nhau loại bỏ max đầu tiên để tìm max thứ hai.
Cú pháp
SELECT
(SELECT MAX(cotLuong) FROM bang) AS MaxSalary,
(SELECT MAX(cotLuong) FROM bang
WHERE cotLuong NOT IN (SELECT MAX(cotLuong) FROM bang)) AS SecondMaxSalary;
Ví dụ minh họa
Bảng EmployeeMaxAndSecondMaxSalary:
CREATE TABLE EmployeeMaxAndSecondMaxSalary (
EmployeeId INT, EmployeeName VARCHAR(20), EmployeeSalary INT
);
INSERT INTO EmployeeMaxAndSecondMaxSalary VALUES
(1,'John',34566), (2,'Bob',56789), (3,'Carol',44560),
(4,'Sam',76456), (5,'Mike',65566), (6,'David',89990),
(7,'James',68789), (8,'Robert',76543);
Truy vấn:
SELECT
(SELECT MAX(EmployeeSalary) FROM EmployeeMaxAndSecondMaxSalary) AS MaximumSalary,
(SELECT MAX(EmployeeSalary) FROM EmployeeMaxAndSecondMaxSalary
WHERE EmployeeSalary NOT IN (SELECT MAX(EmployeeSalary) FROM EmployeeMaxAndSecondMaxSalary))
AS SecondMaximumSalary;
Kết quả
+---------------+---------------------+
| MaximumSalary | SecondMaximumSalary |
+---------------+---------------------+
| 89990 | 76543 |
+---------------+---------------------+
Các phương pháp thay thế
- LIMIT OFFSET (đơn giản, xem bài sau):
SELECT EmployeeSalary FROM EmployeeMaxAndSecondMaxSalary ORDER BY EmployeeSalary DESC LIMIT 1 OFFSET 1; - DISTINCT + LIMIT (xử lý trùng lương):
SELECT DISTINCT EmployeeSalary FROM EmployeeMaxAndSecondMaxSalary ORDER BY EmployeeSalary DESC LIMIT 1 OFFSET 1; - Window Function (MySQL 8.0+):
SELECT DISTINCT EmployeeSalary, ROW_NUMBER() OVER (ORDER BY EmployeeSalary DESC) AS rn FROM EmployeeMaxAndSecondMaxSalary QUALIFY rn = 2; -- MySQL chưa hỗ trợ QUALIFY, dùng CTE
Lưu ý
- Subquery NOT IN chậm trên bảng lớn (có thể rewrite thành LEFT JOIN / NOT EXISTS).
- Nếu nhiều người cùng lương max → SecondMax là lương thấp hơn max (không phải người thứ 2).
- Dùng
DISTINCTnếu muốn lương thứ 2 riêng biệt.