MySQL部门工资最高的员工

淡淡的烟草味﹌ 2023-10-06 18:50 153阅读 0赞

MySQL部门工资最高的员工

  • SQL架构
  • 题目描述
  • 题解
    • 方法:使用 JOIN 和 IN 语句
    • 方法2
    • 方法: GROUP BY 语句
  • 知识点
    • exists 和 in
      • 1.原理
      • 2.分析
      • 3.总结
      • 4.效率
      • 5.举例说明

SQL架构

  1. Create table If Not Exists Employee (Id int, Name varchar(255), Salary int, DepartmentId int);
  2. Create table If Not Exists Department (Id int, Name varchar(255));
  3. insert into Employee (Id, Name, Salary, DepartmentId) values ('1', 'Joe', '70000', '1');
  4. insert into Employee (Id, Name, Salary, DepartmentId) values ('2', 'Jim', '90000', '1');
  5. insert into Employee (Id, Name, Salary, DepartmentId) values ('3', 'Henry', '80000', '2');
  6. insert into Employee (Id, Name, Salary, DepartmentId) values ('4', 'Sam', '60000', '2');
  7. insert into Employee (Id, Name, Salary, DepartmentId) values ('5', 'Max', '90000', '1');
  8. insert into Department (Id, Name) values ('1', 'IT');
  9. insert into Department (Id, Name) values ('2', 'Sales');

题目描述

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

  1. +----+-------+--------+--------------+
  2. | Id | Name | Salary | DepartmentId |
  3. +----+-------+--------+--------------+
  4. | 1 | Joe | 70000 | 1 |
  5. | 2 | Jim | 90000 | 1 |
  6. | 3 | Henry | 80000 | 2 |
  7. | 4 | Sam | 60000 | 2 |
  8. | 5 | Max | 90000 | 1 |
  9. +----+-------+--------+--------------+

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

  1. +----+----------+
  2. | Id | Name |
  3. +----+----------+
  4. | 1 | IT |
  5. | 2 | Sales |
  6. +----+----------+

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

  1. +------------+----------+--------+
  2. | Department | Employee | Salary |
  3. +------------+----------+--------+
  4. | IT | Max | 90000 |
  5. | IT | Jim | 90000 |
  6. | Sales | Henry | 80000 |
  7. +------------+----------+--------+

解释:

Max 和 Jim 在 IT 部门的工资都是最高的,Henry 在销售部的工资最高。

题解

方法:使用 JOIN 和 IN 语句

算法

因为 Employee 表包含 Salary 和 DepartmentId 字段,我们可以以此在部门内查询最高工资。

  1. SELECT
  2. DepartmentId, MAX(Salary)
  3. FROM
  4. Employee
  5. GROUP BY DepartmentId;

注意:有可能有多个员工同时拥有最高工资,所以最好在这个查询中不包含雇员名字的信息。

  1. +--------------+-------------+
  2. | DepartmentId | MAX(Salary) |
  3. +--------------+-------------+
  4. | 1 | 90000 |
  5. | 2 | 80000 |
  6. +--------------+-------------+
  7. 2 rows in set (0.00 sec)

然后,我们可以把表 Employee 和 Department 连接,再在这张临时表里用 IN 语句查询部门名字和工资的关系。

  1. SELECT
  2. Department.name AS 'Department',
  3. Employee.name AS 'Employee',
  4. Salary
  5. FROM
  6. Employee
  7. JOIN
  8. Department ON Employee.DepartmentId = Department.Id
  9. WHERE
  10. (Employee.DepartmentId , Salary) IN
  11. ( SELECT
  12. DepartmentId, MAX(Salary)
  13. FROM
  14. Employee
  15. GROUP BY DepartmentId
  16. );
  17. +------------+----------+--------+
  18. | Department | Employee | Salary |
  19. +------------+----------+--------+
  20. | IT | Jim | 90000 |
  21. | Sales | Henry | 80000 |
  22. | IT | Max | 90000 |
  23. +------------+----------+--------+
  24. 3 rows in set (0.00 sec)

方法2

  1. select bb.Name as Department, aa.Employee, aa.Salary
  2. from (
  3. select
  4. a.Id,
  5. a.Name as Employee,
  6. a.Salary,
  7. a.DepartmentId
  8. from Employee a
  9. join (
  10. select DepartmentId, max(Salary) as max_sal
  11. from Employee
  12. group by DepartmentId
  13. ) b on a.DepartmentId = b.DepartmentId and a.Salary = b.max_sal
  14. ) aa
  15. join Department bb on aa.DepartmentId = bb.Id;
  16. +------------+----------+--------+
  17. | Department | Employee | Salary |
  18. +------------+----------+--------+
  19. | IT | Jim | 90000 |
  20. | Sales | Henry | 80000 |
  21. | IT | Max | 90000 |
  22. +------------+----------+--------+
  23. 3 rows in set (0.01 sec)

方法: GROUP BY 语句

  1. SELECT
  2. Department.NAME AS Department,
  3. Employee.NAME AS Employee,
  4. Salary
  5. FROM
  6. Employee,
  7. Department
  8. WHERE
  9. Employee.DepartmentId = Department.Id
  10. AND ( Employee.DepartmentId, Salary )
  11. IN (SELECT DepartmentId, max( Salary )
  12. FROM Employee
  13. GROUP BY DepartmentId );
  14. +------------+----------+--------+
  15. | Department | Employee | Salary |
  16. +------------+----------+--------+
  17. | IT | Jim | 90000 |
  18. | Sales | Henry | 80000 |
  19. | IT | Max | 90000 |
  20. +------------+----------+--------+
  21. 3 rows in set (0.00 sec)
  22. SELECT D.Name AS Department,
  23. E1.Name AS Employee,
  24. E1.Salary
  25. FROM Employee AS E1
  26. INNER JOIN Department AS D
  27. ON E1.DepartmentId = D.Id
  28. WHERE NOT EXISTS (SELECT *
  29. FROM Employee AS E2
  30. WHERE E1.DepartmentId = E2.DepartmentId
  31. AND E1.Salary < E2.Salary);

知识点

exists 和 in

1.原理

通过使用 EXISTS,Oracle会首先检查主查询,然后运行子查询直到它找到第一个匹配项,
这就节省了时间。

Oracle在执行IN子查询时,首先执行子查询,并将获得的结果列表存放在一个加了索引的临时表中。

在执行子查询之前,系统先将主查询挂起,待子查询执行完毕,存放在临时表中以后再执行主查询。

这也就是使用EXISTS比使用IN通常查询速度快的原因。

2.分析

in 是把外表和内表作hash 连接,而exists是对外表作loop循环。

每次loop循环再对内表进行查询not exists:做NLL,对子查询先查,有个虚表,有确定值,所以就算子查询有NULL最终也有值返回not in:做hash,对子查询表建立内存数组,用外表匹配,那子查询要是NULL那外表没的匹配最终无值返回。

一直以来认为exists比in效率高的说法是不准确的。

但是,如果查询的两个表大小相当,那么用in和exists差别不大。

3.总结

外表大,用IN;内表大,用EXISTS。

4.效率

  1. - select * from T1 where exists(select 1 from T2 where T1.a=T2.a) ;
  2. T1数据量小而T2数据量非常大时,T1<<T2 时,1) 的查询效率高。
  3. - select * from T1 where T1.a in (select T2.a from T2);
  4. T1数据量非常大而T2数据量小时,T1>>T2 时,2) 的查询效率高。

5.举例说明

  1. 例如:表A(小表),表B(大表)
  2. 1 select * from A where cc in (select cc from B)
  3. 效率低,用到了A表上cc列的索引;
  4. select * from A where exists(select cc from B where cc=A.cc)
  5. 效率高,用到了B表上cc列的索引。
  6. 2. select * from B where cc in (select cc from A)
  7. 效率高,用到了B表上cc列的索引;
  8. select * from B where exists(select cc from A where cc=B.cc)
  9. 效率低,用到了A表上cc列的索引。

发表评论

表情:
评论列表 (有 0 条评论,153人围观)

还没有评论,来说两句吧...

相关阅读