zoukankan      html  css  js  c++  java
  • 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 e.DepartmentId, e.Name, e.Salary
    FROM Employee AS e
    WHERE (SELECT COUNT(DISTINCT e2.Salary)
    FROM Employee AS e2
    WHERE e.DepartmentId=e2.DepartmentId
    AND e2.Salary>e.Salary) < 3;

    这里的解题思路是,先使用关联子查询把相同部门的员工归在一起,然后条件筛选出比各个员工工资高的员工,如果这些筛选出的员工的数量小于3个,那就说明进行对比的这些员工排在前三位。比如,如果你排在你们部门第一位,那么就有0个人的工资比你高,如果你排在第三位,那么就有2个人的工资比你高。

    可以看到,上面关联的两张表其实是相同的两张表,因此也可以用自连接来解题,但是由于此种方式没有关联子查询来得清晰,因此这里就不表了。

  • 相关阅读:
    C风格字符串大写转小写
    指针的引用在函数中的应用
    Debug和Release区别
    差分约束系统(System Of Difference Constraints)
    poj_2299UltraQuickSort && poj_1804Brainman
    计算几何基础——矢量和叉积
    推荐ALGORITHM专题
    后缀数组之倍增法
    静态邻接表的简单实现
    归并排序&&树状数组求逆序数
  • 原文地址:https://www.cnblogs.com/HuZihu/p/12469204.html
Copyright © 2011-2022 走看看