Trouvez le 3ème salaire maximum pour chaque département en fonction des données de la table

J'ai besoin de find le 3rd maximum salary pour un employé pour chaque département dans un table . s'il n'y a pas de 3rd maximum salary alors affichez le 2nd maximum salary . s'il n'existe pas de 2nd maximum salary trouvez le highest salary le highest salary . Comment atteindre ce résultat dans sql-server ?

La structure de la table est donnée ci-dessous

 create table employee1(empid int, empname varchar(10), deptid int, salary money) insert into employee1 select 1,'a',1, 1000 union select 1,'b',1, 1200 union select 1,'c',1, 1500 union select 1,'c',1, 15700 union select 1,'d',2, 1000 union select 1,'e',2, 1200 union select 1,'g',3, 1500 

J'ai essayé la façon commune d'get le salaire maximum pour chaque catégorie en utilisant la fonction row_number .

 ;with cte as ( select ROW_NUMBER( ) over( partition by deptid order by salary) as id, * from employee1 ) select * from cte 

 Select EmpID,empname,deptid,salary From ( Select * ,RN = Row_Number() over (Partition By deptid Order By Salary) ,Cnt = sum(1) over (Partition By deptid) From employee1 ) A Where RN = case when Cnt<3 then Cnt else 3 end 

Résultats

entrez la description de l'image ici

La réponse dépendra si vous voulez des liens et comment les gérer. Si vous ne voulez pas de liens et même si un employé est lié à un autre, il devient le salaire le plus élevé, alors l'astuce consiste à utiliser un row_number comme celui que vous montrez avec descendant sur le salaire et ensuite utiliser un autre row_number pour l'inverser. Si vous ne voulez pas utiliser row_number une seconde fois, vous pouvez le faire avec quelques autres techniques, mais l'étape 1 est la plus haute. L'étape 2 consiste à inverser cet ordre.

 ; WITH cteRankSalariesByDepartment AS ( SELECT * ,RowNum = DENSE_RANK() OVER (PARTITION BY deptid ORDER BY salary DESC) FROM employee1 ) , cteReverseRankHighestSalaries AS ( SELECT * ,RowNum2 = DENSE_RANK() OVER (PARTITION BY deptid ORDER BY RowNum DESC) FROM cteRankSalariesByDepartment WHERE RowNum <= 3 ) SELECT * FROM cteReverseRankHighestSalaries WHERE RowNum2 = 1 

Par votre commentaire mis à jour à DENSE_RANK() vous pouvez simplement l'utiliser à la place de row_number() et vous obtiendrez vos liens.

Juste vous requête nécessite count et row_number avec condition comme ci-dessous:

 ;with cte as ( select ROW_NUMBER( ) over( partition by deptid order by salary desc) as id, Cnt = count(*) over(partition by deptid), * from employee1 ) select * from cte where ( cnt >= 3 and id = 3 ) or ( cnt < 3 and id = 1 ) 

vous pouvez essayer une requête comme ci-dessous:

 select * from ( select empid, empname , deptid , salary , ROW_NUMBER( ) over( partition by deptid order by id desc) as rev_id from ( select ROW_NUMBER( ) over( partition by deptid order by salary) as id, empid, empname , deptid , salary from employee1 ) t where id<=3 )t where rev_id=1 

démo de travail

Vous pourriez utiliser UNION

 ;with cte as ( select ROW_NUMBER( ) over( partition by deptid order by salary) as id, * from employee1 ) --get the 3rd highest select * from cte where id = 3 union --get the highest / max select c.* from cte c --this determines the highest which salary for each dept inner join (select deptid, max(id) id from cte group by deptid) x on x.deptid = c.deptid and x.id = c.id --this limits it on depts that aren't in the list in the first part of the query where c.deptid not in (select deptid from cte where id = 3) 

Pour augmenter votre question j'ai ajouté deux employés avec le même salaire dans la troisième position.

Pour get ceci, vous devez d'abord calculer le salaire par département. Après avoir besoin d'inverser le rang de salaire et get la position 1

essayez-le

  DECLARE @employee1 TABLE ( empid INT, empname VARCHAR(10), deptid INT, salary MONEY ) INSERT @employee1 Values (1,'a',1, 1000 ) ,(1,'b',1, 1200 ) ,(2,'bb',1, 1200 ) ,(1,'c',1, 1500 ) ,(3,'ccc',1, 1500 ) ,(1,'c',1, 15700) ,(1,'d',2, 1000 ) ,(1,'e',2, 1200 ) ,(1,'g',3, 1500 ) WITH cte_rank AS (SELECT Dense_rank() OVER ( partition BY deptid ORDER BY salary) SalaryRank, * FROM @employee1), cte_final AS (SELECT Dense_rank() OVER ( partition BY deptid ORDER BY salaryrank DESC) SalaryRankReverse, * FROM cte_rank WHERE salaryrank <= 3) SELECT * FROM cte_final WHERE salaryrankreverse = 1 

Résultat

 SalaryRankReverse SalaryRank empid empname deptid salary -------------------- -------------------- ----------- ---------- ----------- --------------------- 1 3 1 c 1 1500.00 1 3 3 ccc 1 1500.00 1 2 1 e 2 1200.00 1 1 1 g 3 1500.00