Hai bài "vào tay" xuất hiện trong hầu hết vòng SQL:
Lương cao thứ 2 (phải xử lý trùng lương và trường hợp không tồn tại):
sql
-- Cách 1: subquery — trả NULL nếu không có (đúng yêu cầu đề)
SELECT MAX(salary) AS second_highest
FROM employees
WHERE salary < (SELECT MAX(salary) FROM employees);
-- Cách 2: DENSE_RANK — tổng quát hóa cho "cao thứ N"
SELECT salary FROM (
SELECT salary, DENSE_RANK() OVER (ORDER BY salary DESC) AS rnk
FROM employees
) t WHERE rnk = 2;Dùng DENSE_RANK (không phải ROW_NUMBER/RANK) vì lương trùng phải tính cùng một hạng, không nhảy số. Biến thể LIMIT 1 OFFSET 1 cần SELECT DISTINCT salary, và trả 0 hàng thay vì NULL khi không có — điểm hay bị bắt bẻ.
Top-N mỗi nhóm (3 người lương cao nhất mỗi phòng):
sql
SELECT * FROM (
SELECT e.*, DENSE_RANK() OVER (
PARTITION BY dept_id ORDER BY salary DESC
) AS rnk
FROM employees e
) t WHERE rnk <= 3;PARTITION BY chia cửa sổ theo nhóm, xếp hạng trong từng nhóm rồi lọc ở ngoài (không lọc trực tiếp được vì window function không dùng được trong WHERE cùng mức).
Nắm chắc bộ ba ROW_NUMBER/RANK/DENSE_RANK + PARTITION BY là giải được cả họ bài này (mới nhất mỗi nhóm, khử trùng lặp, xếp hạng).