题目描述

Employee 表包含所有员工信息,每个员工有其对应的 Id, salary 和 department Id。

Employee 表:

Id Name Salary DepartmentId
1 Joe 70000 1
2 Jim 90000 1
3 Henry 80000 5
4 Sam 60000 5
5 Max 90000 1

Department 表包含公司所有部门的信息。

Department 表:

Id Name
1 IT
2 Sales

编写一个 SQL 查询,找出每个部门工资最高的员工。对于上述表,您的 SQL 查询应返回以下行(行的顺序无关紧要)。

Department Employee Salary
IT Max 90000
IT Jim 90000
Sales Henry 80000

相关知识

此题不需要前置知识

解题过程

  1. 分析题意

    • 将Department表和Employee表进行内连接,条件为Employee.DeparmentId=Deparment.Id
    • 按部门分组,每组内进行并列连续排名
    • 将每个组内并列第一的所有人的Department、Employee、Salary进行输出
  2. 根据178分数排名的解题经验,编写sql

    SELECT
        DepartmentName AS Department,
        `Name` AS Employee,
        Salary
    FROM
        (
            SELECT
                Employee.ID,
                Employee.`Name`,
                Salary,
                DepartmentId,
                Department.`Name` AS DepartmentName,
                DENSE_RANK() OVER(PARTITION BY DepartmentId ORDER BY Salary DESC) AS rank_
            FROM
                Employee,Department
            WHERE
                Employee.DepartmentId=Department.Id
        ) u
    WHERE
        rank_=1
    
  3. 提交,运行通过

  4. 阅读题解,发现其他人有别的写法

    • 先对DepartmentId分组查询最大值,得到不同DepartmentId下的最大值

    • 再根据DepartmentId字段连接Department表,连接条件为Employee.DepartmentId=Department.Id

    • 对连接后的表进行筛选,保证每个元组的DepartmentId和Salary在第一次求出的最大值里

    • sql

      SELECT
          Department.`Name` AS Department,
          Employee.`Name` AS Employee,
          Salary
      FROM
          Employee JOIN Department ON Employee.DepartmentId=Department.Id
      WHERE
          (DepartmentId,Salary)
          IN
          (
              SELECT
                  DepartmentId,
                  MAX(Salary) AS MaxSalary
              FROM
                  Employee
                  GROUP BY
                      DepartmentId
          )
      

学习总结

  1. 此题主要考察外连接,外连接中使用了一个关键字ON,设定连接条件,所以再加上WHERE实际上进行了两次筛选。

  2. 最大值函数:MAX(列名)

  3. 最小值函数:MIN(列名)

  4. 如果要校验几个字段在某个集合中,这个几个字段需要用括号括起来,否则会有语法错误

    (DepartmentId,Salary) IN ......