A maneira de fazer isso é com as funções analíticas do Oracle. Seu cenário específico é apenas uma variante da solução que forneci em outro tópico.
Se você estiver interessado em apenas selecionar o segundo salário mais alto, qualquer um de DENSE_RANK(), RANK() e ROW_NUMBER() fará o truque:
SQL> select * from
2 ( select sal
3 , rank() over (order by sal desc) as rnk
4 from
5 ( select distinct sal
6 from emp )
7 )
8 where rnk = 2
9 /
SAL RNK
---------- ----------
3000 2
SQL>
No entanto, se você quiser selecionar informações adicionais, como o nome do funcionário com o segundo maior salário, a função escolhida afetará o resultado. A principal razão para escolher um em detrimento do outro é o que acontece quando há um empate.
Se você usar ROW_NUMBER(), ele retornará o segundo funcionário ordenado por salário:e se houver dois funcionários empatados pelo salário mais alto? E se houver dois funcionários empatados pelo segundo maior salário? Se você usar RANK() e houver dois funcionários empatados pelo primeiro salário mais alto, não haverá não registros com RANK =2.
Sugiro que DENSE_RANK() seja a função geralmente mais segura para escolher nesses casos, mas realmente depende do requisito de negócios específico.