题解

SELECT t_dep_maxsal.dep_no,s.emp_no,t_dep_maxsal.dep_maxsal FROM(
    SELECT dep_no,MAX(sal) dep_maxsal FROM (
    SELECT de.dept_no dep_no,de.emp_no emp_no,salary sal
    FROM dept_emp de
    JOIN salaries s
    ON de.emp_no=s.emp_no
    ) t_dep_emp_sal
    GROUP BY t_dep_emp_sal.dep_no
)t_dep_maxsal
LEFT JOIN salaries s
ON t_dep_maxsal.dep_maxsal=s.salary
AND s.emp_no IN( SELECT emp_no FROM dept_emp WHERE dept_no=t_dep_maxsal.dep_no)
ORDER BY dep_no ASC;

测试数据与题解详细说明

测试数据:

#测试数据1
INSERT INTO dept_emp VALUES(10001,'d001','1986-06-26','9999-01-01');
INSERT INTO dept_emp VALUES(10002,'d001','1996-08-03','9999-01-01');
INSERT INTO dept_emp VALUES(10003,'d002','1996-08-09','9999-01-01');
INSERT INTO dept_emp VALUES(10004,'d003','1996-08-08','9999-01-01');
INSERT INTO dept_emp VALUES(10005,'d003','1996-08-07','9999-01-01');
INSERT INTO dept_emp VALUES(10006,'d003','1996-08-07','9999-01-01');

INSERT INTO salaries VALUES(10001,78958,'2002-06-22','9999-01-01');
INSERT INTO salaries VALUES(10002,82527,'2001-08-02','9999-01-01');
INSERT INTO salaries VALUES(10003,92527,'2001-08-07','9999-01-01');
INSERT INTO salaries VALUES(10004,82527,'2001-08-08','9999-01-01');
INSERT INTO salaries VALUES(10005,53527,'2001-08-06','9999-01-01');
INSERT INTO salaries VALUES(10006,93527,'2001-08-06','9999-01-01');

#测试数据1-表数据
SELECT * FROM dept_emp;
+--------+---------+------------+------------+
| emp_no | dept_no | from_date  | to_date    |
+--------+---------+------------+------------+
|  10001 | d001    | 1986-06-26 | 9999-01-01 |
|  10002 | d001    | 1996-08-03 | 9999-01-01 |
|  10003 | d002    | 1996-08-09 | 9999-01-01 |
|  10004 | d003    | 1996-08-08 | 9999-01-01 |
|  10005 | d003    | 1996-08-07 | 9999-01-01 |
|  10006 | d003    | 1996-08-07 | 9999-01-01 |
+--------+---------+------------+------------+
6 ROWS IN SET (0.00 sec)

SELECT * FROM salaries;
+--------+--------+------------+------------+
| emp_no | salary | from_date  | to_date    |
+--------+--------+------------+------------+
|  10001 |  78958 | 2002-06-22 | 9999-01-01 |
|  10002 |  82527 | 2001-08-02 | 9999-01-01 |
|  10003 |  92527 | 2001-08-07 | 9999-01-01 |
|  10004 |  82527 | 2001-08-08 | 9999-01-01 |
|  10005 |  53527 | 2001-08-06 | 9999-01-01 |
|  10006 |  93527 | 2001-08-06 | 9999-01-01 |
+--------+--------+------------+------------+
6 ROWS IN SET (0.00 sec)

#测试数据2
INSERT INTO dept_emp VALUES(10001,'d001','1986-06-26','9999-01-01');
INSERT INTO dept_emp VALUES(10002,'d001','1996-08-03','9999-01-01');
INSERT INTO dept_emp VALUES(10003,'d002','1996-08-09','9999-01-01');
INSERT INTO dept_emp VALUES(10004,'d003','1996-08-08','9999-01-01');
INSERT INTO dept_emp VALUES(10005,'d003','1996-08-07','9999-01-01');
INSERT INTO dept_emp VALUES(10006,'d003','1996-08-07','9999-01-01');
INSERT INTO dept_emp VALUES(10007,'d002','1996-08-07','9999-01-01');
INSERT INTO dept_emp VALUES(10008,'d002','1996-08-07','9999-01-01');

INSERT INTO salaries VALUES(10001,78958,'2002-06-22','9999-01-01');
INSERT INTO salaries VALUES(10002,82527,'2001-08-02','9999-01-01');
INSERT INTO salaries VALUES(10003,92527,'2001-08-07','9999-01-01');
INSERT INTO salaries VALUES(10004,82527,'2001-08-08','9999-01-01');
INSERT INTO salaries VALUES(10005,53527,'2001-08-06','9999-01-01');
INSERT INTO salaries VALUES(10006,93527,'2001-08-06','9999-01-01');
INSERT INTO salaries VALUES(10007,94527,'2001-08-06','9999-01-01');
INSERT INTO salaries VALUES(10008,94527,'2001-08-06','9999-01-01');

#测试数据2-表数据
SELECT * FROM dept_emp;
+--------+---------+------------+------------+
| emp_no | dept_no | from_date  | to_date    |
+--------+---------+------------+------------+
|  10001 | d001    | 1986-06-26 | 9999-01-01 |
|  10002 | d001    | 1996-08-03 | 9999-01-01 |
|  10003 | d002    | 1996-08-09 | 9999-01-01 |
|  10004 | d003    | 1996-08-08 | 9999-01-01 |
|  10005 | d003    | 1996-08-07 | 9999-01-01 |
|  10006 | d003    | 1996-08-07 | 9999-01-01 |
|  10007 | d002    | 1996-08-07 | 9999-01-01 |
|  10008 | d002    | 1996-08-07 | 9999-01-01 |
+--------+---------+------------+------------+
8 ROWS IN SET (0.00 sec)

SELECT * FROM salaries;
+--------+--------+------------+------------+
| emp_no | salary | from_date  | to_date    |
+--------+--------+------------+------------+
|  10001 |  78958 | 2002-06-22 | 9999-01-01 |
|  10002 |  82527 | 2001-08-02 | 9999-01-01 |
|  10003 |  92527 | 2001-08-07 | 9999-01-01 |
|  10004 |  82527 | 2001-08-08 | 9999-01-01 |
|  10005 |  53527 | 2001-08-06 | 9999-01-01 |
|  10006 |  93527 | 2001-08-06 | 9999-01-01 |
|  10007 |  94527 | 2001-08-06 | 9999-01-01 |
|  10008 |  94527 | 2001-08-06 | 9999-01-01 |
+--------+--------+------------+------------+
8 ROWS IN SET (0.00 sec)

题解详细说明:

★★★使用测试数据1
1.1、连接查询-得到部门id与员工id及其工资
SELECT de.dept_no,de.emp_no,salary
FROM dept_emp de
JOIN salaries s
ON de.emp_no=s.emp_no;
+---------+--------+--------+
| dept_no | emp_no | salary |
+---------+--------+--------+
| d001    |  10001 |  78958 |
| d001    |  10002 |  82527 |
| d002    |  10003 |  92527 |
| d003    |  10004 |  82527 |
| d003    |  10005 |  53527 |
| d003    |  10006 |  93527 |
+---------+--------+--------+
6 ROWS IN SET (0.00 sec)

1.2、子查询+分组查询-将1.1查询结果作为临时表(from子查询),以部门id分组,得到各部门最高工资
SELECT dep_no,MAX(sal) FROM (
    SELECT de.dept_no dep_no,de.emp_no emp_no,salary sal
    FROM dept_emp de
    JOIN salaries s
    ON de.emp_no=s.emp_no
) t_dep_emp_sal
GROUP BY t_dep_emp_sal.dep_no;
+--------+----------+
| dep_no | MAX(sal) |
+--------+----------+
| d001   |    82527 |
| d002   |    92527 |
| d003   |    93527 |
+--------+----------+
3 ROWS IN SET (0.00 sec)

1.3、子查询+连接查询-把1.2查询结果作为临时表(from子查询),连接薪资表,得到与最高薪资相同的员工id(这时部门id与员工id有不匹配的数据)
SELECT t_dep_maxsal.dep_no,s.emp_no,t_dep_maxsal.dep_maxsal FROM(
    SELECT dep_no,MAX(sal) dep_maxsal FROM (
    SELECT de.dept_no dep_no,de.emp_no emp_no,salary sal
    FROM dept_emp de
    JOIN salaries s
    ON de.emp_no=s.emp_no
    ) t_dep_emp_sal
    GROUP BY t_dep_emp_sal.dep_no
)t_dep_maxsal
LEFT JOIN salaries s
ON t_dep_maxsal.dep_maxsal=s.salary;
+--------+--------+------------+
| dep_no | emp_no | dep_maxsal |
+--------+--------+------------+
| d001   |  10002 |      82527 |
| d001   |  10004 |      82527 |
| d002   |  10003 |      92527 |
| d003   |  10006 |      93527 |
+--------+--------+------------+
4 ROWS IN SET (0.00 sec)

1.4、在1.3的基础上继续筛选; 条件:员工需是该部门的员工  最后再按部门id升序排序
SELECT t_dep_maxsal.dep_no,s.emp_no,t_dep_maxsal.dep_maxsal FROM(
    SELECT dep_no,MAX(sal) dep_maxsal FROM (
    SELECT de.dept_no dep_no,de.emp_no emp_no,salary sal
    FROM dept_emp de
    JOIN salaries s
    ON de.emp_no=s.emp_no
    ) t_dep_emp_sal
    GROUP BY t_dep_emp_sal.dep_no
)t_dep_maxsal
LEFT JOIN salaries s
ON t_dep_maxsal.dep_maxsal=s.salary
AND s.emp_no IN( SELECT emp_no FROM dept_emp WHERE dept_no=t_dep_maxsal.dep_no)
ORDER BY dep_no ASC;
+--------+--------+------------+
| dep_no | emp_no | dep_maxsal |
+--------+--------+------------+
| d001   |  10002 |      82527 |
| d002   |  10003 |      92527 |
| d003   |  10006 |      93527 |
+--------+--------+------------+
3 ROWS IN SET (0.00 sec)

★★★使用测试数据2
数据说明:同一个部门有两个员工薪资相同且是部门最高薪资
SELECT t_dep_maxsal.dep_no,s.emp_no,t_dep_maxsal.dep_maxsal FROM(
    SELECT dep_no,MAX(sal) dep_maxsal FROM (
    SELECT de.dept_no dep_no,de.emp_no emp_no,salary sal
    FROM dept_emp de
    JOIN salaries s
    ON de.emp_no=s.emp_no
    ) t_dep_emp_sal
    GROUP BY t_dep_emp_sal.dep_no
)t_dep_maxsal
LEFT JOIN salaries s
ON t_dep_maxsal.dep_maxsal=s.salary
AND s.emp_no IN( SELECT emp_no FROM dept_emp WHERE dept_no=t_dep_maxsal.dep_no)
ORDER BY dep_no ASC;
+--------+--------+------------+
| dep_no | emp_no | dep_maxsal |
+--------+--------+------------+
| d001   |  10002 |      82527 |
| d002   |  10007 |      94527 |
| d002   |  10008 |      94527 |
| d003   |  10006 |      93527 |
+--------+--------+------------+
4 rows in set (0.00 sec)
题目要求是获取每个部门中当前员工薪水最高的相关信息,所以要把部门2这两个员工信息都查询出来,符合题意。

关于分组查询(分组函数)的一些问题

  1. 分组函数在使用的时候必须先进行分组,然后才能用,如果没有对数据进行分组,整张表默认为一组。
  2. 和分组函数一同查询的字段要求是group by后的字段(在一条select语句当中,如果有group by语句的话,select后面只能跟:参加分组的字段,以及分组函数,其它的一律不能跟)
    SELECT AVG(salary),employee_id FROM employees GROUP BY employee_id; 可执行
    SELECT AVG(salary),employee_id,job_id FROM employees GROUP BY employee_id;该语句mysql中可以执行,但无意义;oracle中执行报错;