这部分主要是为了帮助大家回忆回忆MySQL的基本语法,数据库来自于MySQL的官方简化版,题目也是网上非常流行的35题。这些基础习题基本可以涵盖面试中需要现场写SQL的问题。
求平均薪水的等级最高的部门的部门名称
Solution:
先求各部门平均薪水的等级,再求最高等级,最后显示平均薪水等级等于最高等级的部门名称
Operation:
1
select a.deptno,a.avgsal,b.grade from (select deptno,avg(sal) as avgsal from emp group by deptno) a join salgrade b on avgsal between losal and hisal;
+--------+-------------+-------+
| deptno | avgsal | grade |
+--------+-------------+-------+
| 20 | 2175.000000 | 4 |
| 30 | 1566.666667 | 3 |
| 10 | 2916.666667 | 4 |
+--------+-------------+-------+
2
+-------+
| grade |
+-------+
| 4 |
+-------+
mysql> select d.dname,c.avgsal,c.grade
from
(select a.deptno,a.avgsal,b.grade
from
(select deptno,avg(sal) as avgsal from emp group by deptno) a
join
salgrade b
on
avgsal between losal and hisal) c
join
dept d
on
c.deptno=d.deptno and c.grade=
(select b.grade from (select deptno,avg(sal) as avgsal from emp group by deptno) a join salgrade b on avgsal between losal and hisal order by b.grade desc limit 1);
+-------------+-------------+-------+
| dname | avgsal | grade |
+-------------+-------------+-------+
| ACCOUNTING | 2916.666667 | 4 |
| RESEARCHING | 2175.000000 | 4 |
+-------------+-------------+-------+
- 内层查询 (子查询 c):
内层查询使用了一个子查询 c,通过联结 emp 表和 salgrade 表计算每个部门的平均工资,并根据平均工资匹配相应的工资等级。 子查询 c 的主要目的是找到每个部门的平均工资以及相应的工资等级。
- 外层查询 (主查询):
外层查询从 dept 表中检索部门的名称,然后与子查询 c 进行联结,以获取子查询返回的结果集中的平均工资和工资等级。 外层查询中的联结条件是 c.deptno = d.deptno,确保每个部门的平均工资和工资等级都与正确的部门关联。 外层查询还包括了一个条件 c.grade = (select ... limit 1),它使用了一个子查询来查找具有最高工资等级的部门的工资等级。
- 内层子查询 (子查询 b):
这个子查询用于计算每个部门的平均工资,并根据平均工资匹配相应的工资等级。 子查询 b 中首先计算每个部门的平均工资,然后与 salgrade 表进行联结,并按照工资等级降序排序。 最后,使用 LIMIT 1 来限制结果集返回最高工资等级的部门。
取得比普通员工(员工代码没在mgr字段出现的)最高薪水更高的领导人姓名
Solution:
先取出普通员工的最高薪水,注意mgr字段里有null,不能直接使用not in 语句。取得所有领导人的姓名和薪水。然后取得结果。
Operation:
找出所有不是其他员工的经理的员工的最高工资
mysql> select max(sal) as cmsal from emp where empno not in (select distinct mgr from emp where mgr is not null);
+---------+
| cmsal |
+---------+
| 1600.00 |
+---------+
找出管理层员工,并且列出他们的姓名和薪水
mysql> select ename,sal from emp where empno in (select distinct mgr from emp);
+-------+---------+
| ename | sal |
+-------+---------+
| FORD | 3000.00 |
| BLAKE | 2850.00 |
| KING | 5000.00 |
| JONES | 2975.00 |
| SCOTT | 3000.00 |
| CLARK | 2450.00 |
+-------+---------+
-
SELECT DISTINCT mgr FROM emp WHERE mgr IS NOT NULL:这部分子查询用于获取所有不是其他员工的经理的员工的经理编号(mgr字段)。使用DISTINCT确保返回的mgr字段值是唯一的,避免重复。
-
SELECT MAX(sal) AS cmsal FROM emp WHERE empno NOT IN (...):这部分子查询计算所有不是其他员工的经理的员工的最高工资。它通过在emp表中选择所有不是其他员工的经理的员工(即不在上述子查询中的员工)来实现。MAX函数用于找到这些员工中工资的最高值。
-
WHERE empno IN (...) AND sal > (...):这是主查询的条件部分,它同时使用了两个子查询的结果作为条件。前一个子查询筛选了作为其他员工的经理的员工,而后一个子查询计算了不是其他员工的经理的员工的最高工资。因此,这个条件确保了只选择薪水高于最高工资的经理。
-
SELECT ename, sal FROM emp ...:这是主查询的主体部分,它选择了符合上述条件的员工的姓名(ename)和薪水(sal)。
mysql> select ename,sal from emp where empno in (select distinct mgr from emp) and sal>(select max(sal) as cmsal from emp where empno not in (select distinct mgr from emp where mgr is not null));
+-------+---------+
| ename | sal |
+-------+---------+
| JONES | 2975.00 |
| BLAKE | 2850.00 |
| CLARK | 2450.00 |
| SCOTT | 3000.00 |
| KING | 5000.00 |
| FORD | 3000.00 |
+-------+---------+
取得薪水最高的前五名员工
select * from emp order by sal desc limit 5;
+-------+-------+-----------+------+------------+---------+------+--------+
| empno | ename | job | mgr | hiredate | sal | comm | deptno |
+-------+-------+-----------+------+------------+---------+------+--------+
| 7839 | KING | PRESIDENT | NULL | 1981-11-17 | 5000.00 | NULL | 10 |
| 7902 | FORD | ANALYST | 7566 | 1981-12-03 | 3000.00 | NULL | 20 |
| 7788 | SCOTT | ANALYST | 7566 | 1987-04-19 | 3000.00 | NULL | 20 |
| 7566 | JONES | MANAGER | 7839 | 1981-04-02 | 2975.00 | NULL | 20 |
| 7698 | BLAKE | MANAGER | 7839 | 1981-05-01 | 2850.00 | NULL | 30 |
+-------+-------+-----------+------+------------+---------+------+--------+
取得薪水最高的第六到第十名员工
mysql> select * from emp order by sal desc limit 5,5;
+-------+--------+----------+------+------------+---------+--------+--------+
| empno | ename | job | mgr | hiredate | sal | comm | deptno |
+-------+--------+----------+------+------------+---------+--------+--------+
| 7782 | CLARK | MANAGER | 7839 | 1981-06-09 | 2450.00 | NULL | 10 |
| 7499 | ALLEN | SALESMAN | 7698 | 1981-02-20 | 1600.00 | 300.00 | 30 |
| 7844 | TURNER | SALESMAN | 7698 | 1981-09-08 | 1500.00 | NULL | 30 |
| 7934 | MILLER | CLERK | 7782 | 1982-01-23 | 1300.00 | NULL | 10 |
| 7521 | WARD | SALESMAN | 7698 | 1981-02-22 | 1250.00 | 500.00 | 30 |
+-------+--------+----------+------+------------+---------+--------+--------+
-
SELECT * FROM emp:这是查询的主体部分,表示从emp表中选择所有列的数据。 -
ORDER BY sal DESC:这部分表示按照薪水字段(sal)进行降序排序。 -
LIMIT 5, 5:这部分表示从结果集中的第6条记录开始,返回接下来的5条记录。第一个数字5表示从第6条记录开始(索引从0开始),第二个数字5表示返回5条记录。
取得最后入职的5名员工
mysql> select * from emp order by hiredate desc limit 5;
+-------+--------+---------+------+------------+---------+------+--------+
| empno | ename | job | mgr | hiredate | sal | comm | deptno |
+-------+--------+---------+------+------------+---------+------+--------+
| 7876 | ADAMS | CLERK | 7788 | 1987-05-23 | 1100.00 | NULL | 20 |
| 7788 | SCOTT | ANALYST | 7566 | 1987-04-19 | 3000.00 | NULL | 20 |
| 7934 | MILLER | CLERK | 7782 | 1982-01-23 | 1300.00 | NULL | 10 |
| 7900 | JAMES | CLERK | 7698 | 1981-12-03 | 950.00 | NULL | 30 |
| 7902 | FORD | ANALYST | 7566 | 1981-12-03 | 3000.00 | NULL | 20 |
+-------+--------+---------+------+------------+---------+------+--------+