2017-09-22 73 views
5

我需要找出table中每个部门的员工的3rd maximum salary。如果不存在3rd maximum salary则显示2nd maximum salary。如果没有2nd maximum salary存在,那么找到highest salary。如何在sql-server中实现这个结果?根据表格数据查找每个部门的第三最大工资

table结构如下

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 

我试图获得最大的薪水为每个类别使用row_number功能的常见方式给出。

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

如果什么有关系?你想要两条记录吗?在这种情况下,如果1人的薪水最高,2人并列第二名,那么你想要第三最高薪水(第四人)还是第二人? – Matt

+0

是啊..我会将row_number更改为dense_rank来解决关系。 – bmsqldev

+1

我更新了答案,你只需要用dense_rank()替换row_number() – Matt

回答

3
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 

返回

enter image description here

+0

没有想到这一点。但如果存在关系并且使用DENSE_RANK()获取它们而不是ROW_NUBMER(),则它不起作用。但我绝对喜欢将不得不添加到我的阿森纳:) – Matt

+1

@Matt正确,对我的耻辱,我从来没有考虑过关系。 : - \ –

3

答案取决于您是否想要关系以及如何处理它们。如果你不需要任何联系,即使一个员工与另一个员工联系,它也会成为下一个最高薪水,那么诀窍就是使用row_number,就像你在薪水中下降时显示的那样,然后使用另一个row_number来反转它。如果你不想使用row_number第二次你可以用一些其他的技术做得一样好,但第1步是找到最高的第2步是扭转这种秩序

; 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 

根据您的意见更新DENSE_RANK()你可以只需使用它代替row_number(),您将获得您的关系。

+0

它在某些情况下返回完全错误的结果:http://rextester.com/OTTA88582 –

+0

@RadimBača我不确定你是否评论过在错误的答案,但你的陈述和例子都与这个答案无关。在你的例子中,你的订单是正确的,并且你正在使用row_number而不是密集的等级来查找关系。首先,您必须按薪水降序排序,将最高薪水排列为第一行,然后您按升序排序薪金,这会将排名最低的那一排作为第一排,因为只要您使用rownum,就可以合理地将rownum用作代理下降,这也是作品 – Matt

+1

对不起,我犯了一个错误,你的答案是好的。像计数技巧一样, –

1

你可以尝试查询象下面这样:

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 

working demo

1

你可以使用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) 
2

只要你查询的需求数与条件ROW_NUMBER如下:

;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) 
-1

要增加你的问题我加了两个员工,在第三位置同样的薪水。

为了得到这个,你需要第一个dense_rank部门的工资。后,您需要倒L的工资等级和获取位置1

尝试

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 

结果

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 
+1

对于第三薪级的第一部分的答案将是1200.00的empid 1和2。你有你的ORDER BY逆转你的ctes,但是当你修复的时候,你会提出我已经发布的答案 – Matt

相关问题