web-dev-qa-db-fra.com

Comment sélectionner l'enregistrement ayant le deuxième salaire le plus élevé dans la base de données Oracle?

Supposons que j'ai un employé de la table avec l'id, le nom d'utilisateur, le salaire. Comment puis-je sélectionner l'enregistrement avec le deuxième salaire le plus élevé dans Oracle?

Je l'ai googlé, trouver cette solution, est-ce que ce qui suit est vrai ?:

select sal from
     (select rownum n,a.* from
        ( select distinct sal from emp order by sal desc) a)
where n = 2;
3
user1801838

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éduit à:

  • ROW_NUMBER () génère toujours un classement unique. si la clause ORDER BY ne peut pas distinguer deux lignes, elle leur donnera quand même un classement différent (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 de rangs contigus (1,2,3, ...), tandis que RANK () laissera des trous après deux rangs ou plus du même rang (pensez "Jeux Olympiques": si deux athlètes gagnent la médaille d'or, il n'y a pas de deuxième place, seulement 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 recommanderais ROW_NUMBER ().

21
Frank Schmitt

Si vous utilisez Oracle 8+, vous pouvez utiliser les fonctions RANK() ou DENSE_RANK() comme suit 

SELECT *
FROM (
  SELECT some_column, 
         rank() over (order by your_sort_column desc) as row_rank
) t
WHERE row_rank = 2;
4
hd1

Cette requête fonctionne dans SQL * PLUS pour connaître le 2e salaire le plus élevé -

SELECT * FROM EMP
WHERE SAL = (SELECT MAX(SAL) FROM EMP
WHERE SAL < (SELECT MAX(SAL) FROM EMP));

Ceci est double sous-requête .

J'espère que ceci vous aide..

3
Sanchit
WITH records
AS
(
    SELECT  id, user_name, salary,
            DENSE_RANK() OVER (PARTITION BY id ORDER BY salary DESC) rn
    FROM    tableName
)
SELECT  id, user_name, salary
FROM    records 
WHERE   rn = 2
2
John Woo

sélectionnez Max (Salary) comme SecondHighestSalary de Employee où Salary n'est pas indiqué dans (sélectionnez max (Salary) de Employee). 

1
pradsav
select * FROM (
select EmployeeID, Salary
, dense_rank() over (order by Salary DESC) ranking
from Employee
)
WHERE ranking = 2;

dense_rank () est utilisé pour le salaire doit être identique.Ainsi, il donne la sortie appropriée au lieu d'utiliser rank () .

1
Md Wasi

Je suggérerais de suivre deux manières d'implémenter ceci dans Oracle.

  1. Utilisation de sous-requête:
select distinct SALARY   
from EMPLOYEE e1  
where 1=(select count(DISTINCT e2.SALARY) from EMPLOYEE e2 where         
  e2.SALARY>e1.SALARY);

Cette requête est très simple pour obtenir la sortie requise. Cependant, cette requête est assez lente car chaque salaire de la requête interne est comparé à tous les salaires distincts.

  1. Utilisation de DENSE_RANK ():
select distinct SALARY   
from
  (
    select e1.*, DENSE_RANK () OVER (order by SALARY desc) as RN 
    from EMPLOYEE e
  ) E
 where E.RN=2;

Cette requête est très efficace. Cela fonctionne bien avec DENSE_RANK (), qui attribue des rangs consécutifs, contrairement à RANK (), qui attribue le rang suivant en fonction du numéro de ligne, ce qui correspond à la médaille olympique.

Différence entre RANK () et DENSE_RANK (): https://Oracle-base.com/articles/misc/rank-dense-rank-first-last-analytic-functions

1
Suraj Shewale

Vous devriez utiliser quelque chose comme ceci:

SELECT *
FROM (select salary2.*, rownum rnum from
         (select * from salary ORDER BY salary_amount DESC) salary2
  where rownum <= 2 )
WHERE rnum >= 2;
1
select * from emp where sal=(select max(sal) from emp where sal<(select max(sal) from emp))

donc dans notre table emp (par défaut fournie par Oracle), voici la sortie

EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO


  7698 BLAKE      MANAGER         7839 01-MAY-81       3000            30
  7788 SCOTT      ANALYST         7566 19-APR-87       3000            20
  7902 FORD       ANALYST         7566 03-DEC-81       3000            20

ou vous voulez simplement que le 2ème salaire maximum soit affiché

select max(sal) from emp where sal<(select max(sal) from emp)

MAX (SAL)

  3000
1
shashank

Je pense que cela donnera le même résultat, sans sous-requête ni fonction de classement:

SELECT *
FROM emp
ORDER BY sal DESC
LIMIT 1
OFFSET 2
0
Jeff Wu
select * from emp where sal = (
select sal from
     (select rownum n,a.sal from
    ( select distinct sal from emp order by sal desc) a)
where n = 2);

C’est plus optimal, cela convient à tous les scénarios ...

0
Rajkumar Pandey
select max(Salary) from EmployeeTest where Salary < ( select max(Salary) from EmployeeTest ) ;

cela fonctionnera pour toutes les bases de données.

0
Ali Saithumuhammed

Cette requête m'aide chaque fois pour des problèmes comme celui-ci. Remplacez N par la position ..

select *
from(
     select *
     from (select * from TABLE_NAME order by SALARY_COLUMN desc)
     where rownum <=N
    )
where SALARY_COLUMN <= all(
                select SALARY_COLUMN
                from (select * from TABLE_NAME order by SALARY_COLUMN desc)
                where rownum <=N
               );
0
Parnab Sanyal