RANK et DENSE_RANK ont déjà été suggérés. En fonction de vos besoins, vous pouvez également envisager ROW_NUMBER() :
select * from (
select e.*, row_number() over (order by sal desc) rn from emp e
)
where rn = 2;
La différence entre RANK(), DENSE_RANK() et ROW_NUMBER() se résume à :
- ROW_NUMBER() génère toujours un classement unique ; si la clause ORDER BY ne peut pas faire la distinction entre deux lignes, elle leur donnera quand même des classements différents (au hasard)
- RANK() et DENSE_RANK() donneront le même classement aux lignes qui ne peuvent pas être distinguées par la clause ORDER BY
- DENSE_RANK() générera toujours une séquence contiguë de rangs (1,2,3,...), tandis que RANK() laissera des espaces après deux lignes ou plus avec le même rang (pensez aux "Jeux Olympiques" :si deux athlètes remportent la médaille d'or, il n'y a pas de deuxième place, seulement la troisième)
Donc, si vous ne voulez qu'un seul employé (même s'il y en a plusieurs avec le deuxième salaire le plus élevé), je vous recommande ROW_NUMBER().