SQL面試題---topN問題


topN問題是SQL面試里經常考的一個問題,即如何取每組最大的N條記錄。

 

這里摘取leetcode上的一道題,因為主要為了說明如何選取topN的記錄,因此這里刪掉了第二張表(不需要進行兩表連接)。

 

題目:根據Employee表中的信息,找出每個部門工資前三高的員工信息(部門號,姓名,工資)

| Id | Name  | Salary | DepartmentId |
+----+-------+--------+--------------+
| 1  | Joe   | 70000  | 1            |
| 2  | Henry | 80000  | 2            |
| 3  | Sam   | 60000  | 2            |
| 4  | Max   | 90000  | 1            |

 

解法一:使用window function

因為這里需要選取的是前三高的工資,如果工資相同,那么排名並列,因此這里用的窗口函數為dense_rank()。

SELECT DepartmentId, Name, Salary,
FROM (SELECT *,
      DENSE_RANK() OVER (PARTTITION BY DepartmentId
      ORDER BY Salary DESC) AS rank
      FROM Employee)
WHERE rank<=3;

這里需要注意的是:因為where在select之前執行,因此如果直接使用rank進行條件篩選會報錯。需要再嵌套一層選擇子句,把之前的語句放入from里面,因為from是最先執行的,因此這樣就不會報錯。

 

使用窗口函數是比較輕松的解法,但是有些數據庫不支持窗口函數,因此很可能面試官會問你,如果不用窗口函數,這題該怎么解?

 

解法二:使用關聯子查詢

SELECT DepartmentId, Name, Salary
FROM Employee
WHERE (SELECT COUNT(DISTINCT e.Salary)
       FROM Employee AS e
       WHERE e.DepartmentId = Employee.DepartmentId
       AND e.Salary > Employee.Salary) < 3

這里的解題思路是,先使用關聯子查詢把相同部門的員工歸在一起,然后條件篩選出比各個員工工資高的員工,如果這些篩選出的員工的數量小於3個,那就說明進行對比的這些員工排在前三位。比如,如果你排在你們部門第一位,那么就有0個人的工資比你高,如果你排在第三位,那么就有2個人的工資比你高。

 

可以看到,上面關聯的兩張表其實是相同的兩張表,因此也可以用自連接來解題,但是由於此種方式沒有關聯子查詢來得清晰,因此這里就不表了。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM