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

相關問題