1、第十五题

15.列出受雇日期早于其直接上级的所有员工编号、姓名、部门名称

思路一:第一步将emp a看成员工表,将emp b 看成领导表,员工表的mgr字段应该等于领导表的主键字段

mysql> select 
    e.empno,
    e.ename
from
    emp e
join
    emp b
on
    e.mgr = b.empno

where
    e.hiredate < b.hiredate;
+-------+-------+
| empno | ename |
+-------+-------+
|  7369 | SMITH |
|  7499 | ALLEN |
|  7521 | WARD  |
|  7566 | JONES |
|  7698 | BLAKE |
|  7782 | CLARK |
|  7876 | ADAMS |
+-------+-------+
7 rows in set

第二步:显示上面员工的部门名称,将emp a员工表和dept d进行关联

mysql> select 
    d.dname,
    e.empno,
    e.ename
from
    emp e
join
    emp b
on
    e.mgr = b.empno
join
    dept d
on
    e.deptno = d.deptno
where
    e.hiredate < b.hiredate;
+------------+-------+-------+
| dname      | empno | ename |
+------------+-------+-------+
| ACCOUNTING |  7782 | CLARK |
| RESEARCH   |  7369 | SMITH |
| RESEARCH   |  7566 | JONES |
| RESEARCH   |  7876 | ADAMS |
| SALES      |  7499 | ALLEN |
| SALES      |  7521 | WARD  |
| SALES      |  7698 | BLAKE |
+------------+-------+-------+
7 rows in set

下面两个题主要考察下左连接和右连接 

14.列出所有员工及领导的名字

mysql> select
    e.ename,
    b.ename as leadername
from
    emp e
left join
    emp b
on
    e.mgr = b.empno;
+--------+------------+
| ename  | leadername |
+--------+------------+
| SMITH  | FORD       |
| ALLEN  | BLAKE      |
| WARD   | BLAKE      |
| JONES  | KING       |
| MARTIN | BLAKE      |
| BLAKE  | KING       |
| CLARK  | KING       |
| SCOTT  | JONES      |
| KING   | NULL       |
| TURNER | BLAKE      |
| ADAMS  | SCOTT      |
| JAMES  | BLAKE      |
| FORD   | JONES      |
| MILLER | CLARK      |
+--------+------------+
14 rows in set

 

下面考查右连接

16.列出部门名称和这些部门的员工信息,同时列出那些没有员工的部门

mysql> select 
    d.dname,
    e.*
from
    emp e
right join
    dept d
on
    e.deptno = d.deptno;
+------------+-------+--------+-----------+------+------------+------+------+--------+
| dname      | EMPNO | ENAME  | JOB       | MGR  | HIREDATE   | SAL  | COMM | DEPTNO |
+------------+-------+--------+-----------+------+------------+------+------+--------+
| ACCOUNTING |  7782 | CLARK  | MANAGER   | 7839 | 1981-06-09 | 2450 | NULL |     10 |
| ACCOUNTING |  7839 | KING   | PRESIDENT | NULL | 1981-11-17 | 5000 | NULL |     10 |
| ACCOUNTING |  7934 | MILLER | CLERK     | 7782 | 1982-01-23 | 1300 | NULL |     10 |
| RESEARCH   |  7369 | SMITH  | CLERK     | 7902 | 1980-12-17 |  800 | NULL |     20 |
| RESEARCH   |  7566 | JONES  | MANAGER   | 7839 | 1981-04-02 | 2975 | NULL |     20 |
| RESEARCH   |  7788 | SCOTT  | ANALYST   | 7566 | 1987-04-19 | 3000 | NULL |     20 |
| RESEARCH   |  7876 | ADAMS  | CLERK     | 7788 | 1981-05-23 | 1100 | NULL |     20 |
| RESEARCH   |  7902 | FORD   | ANALYST   | 7566 | 1981-12-03 | 3000 | NULL |     20 |
| SALES      |  7499 | ALLEN  | SALESMAN  | 7698 | 1981-02-20 | 1600 |  300 |     30 |
| SALES      |  7521 | WARD   | SALESMAN  | 7698 | 1981-02-22 | 1250 |  500 |     30 |
| SALES      |  7654 | MARTIN | SALESMAN  | 7698 | 1981-09-28 | 1250 | 1400 |     30 |
| SALES      |  7698 | BLAKE  | MANAGER   | 7839 | 1981-05-01 | 2850 | NULL |     30 |
| SALES      |  7844 | TURNER | SALESMAN  | 7698 | 1981-09-08 | 1500 |    0 |     30 |
| SALES      |  7900 | JAMES  | CLERK     | 7698 | 1981-12-03 |  950 | NULL |     30 |
| OPERATIONS | NULL  | NULL   | NULL      | NULL | NULL       | NULL | NULL | NULL   |
+------------+-------+--------+-----------+------+------------+------+------+--------+
15 rows in set

 

下面考查having的使用,如果使用了groupby对数据进行设置之后,还需要对数据结构进行限制需要使用having

17.列出至少有5个员工的所有部门

第一步:先求出每个部门有多少员工,将emp a和部门表 dept d表进行关联,条件是e.deptno=d.deptno

第二步:然后通过分组e.deptno,过来count(e.ename) >= 5

mysql> select 
    e.deptno,count(e.ename) as totalEmp
from
    emp e
group by
    e.deptno
having
    totalEmp >= 5;
+--------+----------+
| deptno | totalEmp |
+--------+----------+
|     20 |        5 |
|     30 |        6 |
+--------+----------+
2 rows in set

 

这里比较关键:第一点 使用了group by 字段,select 后面的字段只能是group by后面的字段e.deptno和聚合函数对应的字段count(e.ename) as totalEmp

第二点:现在要对聚合函数的结果进行过滤,totalEmp字段不是数据库中的字段,不能使用where进行限制,只能使用having

 

接下来:考察的是子查询,子查询是在一个数据库表中

18.列出薪水比“SMITH”多的所有员工信息

第一步:首先求出是,smith的工资

第二步:然后求出工资高于simith的

mysql> select * from emp where sal > (select sal from emp where ename = 'SMITH');
+-------+--------+-----------+------+------------+------+------+--------+
| EMPNO | ENAME  | JOB       | MGR  | HIREDATE   | SAL  | COMM | DEPTNO |
+-------+--------+-----------+------+------------+------+------+--------+
|  7499 | ALLEN  | SALESMAN  | 7698 | 1981-02-20 | 1600 |  300 |     30 |
|  7521 | WARD   | SALESMAN  | 7698 | 1981-02-22 | 1250 |  500 |     30 |
|  7566 | JONES  | MANAGER   | 7839 | 1981-04-02 | 2975 | NULL |     20 |
|  7654 | MARTIN | SALESMAN  | 7698 | 1981-09-28 | 1250 | 1400 |     30 |
|  7698 | BLAKE  | MANAGER   | 7839 | 1981-05-01 | 2850 | NULL |     30 |
|  7782 | CLARK  | MANAGER   | 7839 | 1981-06-09 | 2450 | NULL |     10 |
|  7788 | SCOTT  | ANALYST   | 7566 | 1987-04-19 | 3000 | NULL |     20 |
|  7839 | KING   | PRESIDENT | NULL | 1981-11-17 | 5000 | NULL |     10 |
|  7844 | TURNER | SALESMAN  | 7698 | 1981-09-08 | 1500 |    0 |     30 |
|  7876 | ADAMS  | CLERK     | 7788 | 1981-05-23 | 1100 | NULL |     20 |
|  7900 | JAMES  | CLERK     | 7698 | 1981-12-03 |  950 | NULL |     30 |
|  7902 | FORD   | ANALYST   | 7566 | 1981-12-03 | 3000 | NULL |     20 |
|  7934 | MILLER | CLERK     | 7782 | 1982-01-23 | 1300 | NULL |     10 |
+-------+--------+-----------+------+------------+------+------+--------+
13 rows in set

子查询2

21.列出在部门“SALES”<销售部>工作的员工的姓名,假定不知道销售部门的部门编号

select deptno from dept where dname = 'SALES';
+--------+
| deptno |
+--------+
|     30 |
+--------+


select ename from emp where deptno = (select deptno from dept where dname = 'SALES');
+--------+
| ename  |
+--------+
| ALLEN  |
| WARD   |
| MARTIN |
| BLAKE  |
| TURNER |
| JAMES  |

 

子查询三:in

24.列出薪金等于部门30中员工的薪金的其它员工的姓名和薪金
select distinct sal from emp where deptno = 30;
+---------+
| sal     |
+---------+
| 1600.00 |
| 1250.00 |
| 2850.00 |
| 1500.00 |
|  950.00 |
+---------+

select ename,sal from emp where sal in(select distinct sal from emp where deptno = 30) and deptno <> 30;

 

 

19.列出所有“CLERK”(办事员)的姓名及其部门名称,部门人数

这是一个比较综合的题目

1、第一步在emp a表中查询出那些人的job岗位是办事员

2、将emp a表和dept  d表相关联就可以得到职位是办事员的emp对应的部门名称

3、查询出每个部门对应的员工总数

4、将第三步的查询结果作为一个临时表t与第二步的查询结果进行关联,关联条件是t.deptno = d.deptno

select 
    d.deptno,d.dname,e.ename
from
    emp e
join
    dept d
on
    e.deptno = d.deptno
where
    e.job = 'CLERK';
t1
+--------+------------+--------+
| deptno | dname      | ename  |
+--------+------------+--------+
|     10 | ACCOUNTING | MILLER | 3
|     20 | RESEARCH   | SMITH  | 5
|     20 | RESEARCH   | ADAMS  | 5
|     30 | SALES      | JAMES  | 6
+--------+------------+--------+

求出每个部门的员工数量
select
    e.deptno,count(e.ename) as totalEmp
from
    emp e
group by
    e.deptno;
t2
+--------+----------+
| deptno | totalEmp |
+--------+----------+
|     10 |        3 |
|     20 |        5 |
|     30 |        6 |
+--------+----------+


select 
    t1.deptno,t1.dname,t1.ename,t2.totalEmp
from
    (select 
        d.deptno,d.dname,e.ename
    from
        emp e
    join
        dept d
    on
        e.deptno = d.deptno
    where
        e.job = 'CLERK') t1
join
    (select
        e.deptno,count(e.ename) as totalEmp
    from
        emp e
    group by
        e.deptno) t2
on
    t1.deptno = t2.deptno;

+--------+------------+--------+----------+
| deptno | dname      | ename  | totalEmp |
+--------+------------+--------+----------+
|     10 | ACCOUNTING | MILLER |        3 |
|     20 | RESEARCH   | SMITH  |        5 |
|     20 | RESEARCH   | ADAMS  |        5 |
|     30 | SALES      | JAMES  |        6 |
+--------+------------+--------+----------+

 

下面考查在select 后面两个聚合函数的事业

20.列出最低薪水大于1500的各种工作及从事此工作的全部雇员人数

第一步:求出每种工作岗位的最低薪水,并且最低薪水大于15000

第二步:在第一步的基础上求出雇员数量(count *)

第一步:先求出每种工作岗位的最低薪水
select 
    e.job,min(e.sal) as minsal
from
    emp e
group by
    e.job;
+-----------+---------+
| job       | minsal  |
+-----------+---------+
| ANALYST   | 3000.00 |
| CLERK     |  800.00 |
| MANAGER   | 2450.00 |
| PRESIDENT | 5000.00 |
| SALESMAN  | 1250.00 |
+-----------+---------+

select 
    e.job,min(e.sal) as minsal,count(e.ename) as totalEmp
from
    emp e
group by
    e.job
having
    minsal > 1500;
+-----------+---------+
| job       | minsal  |
+-----------+---------+
| ANALYST   | 3000.00 |
| MANAGER   | 2450.00 |
| PRESIDENT | 5000.00 |
+-----------+---------+
+-----------+---------+----------+
| job       | minsal  | totalEmp |
+-----------+---------+----------+
| ANALYST   | 3000.00 |        2 |
| MANAGER   | 2450.00 |        3 |
| PRESIDENT | 5000.00 |        1 |
+-----------+---------+----------+

 

 

接下来是对上面知识点的全部的一个综合的复习

22.列出薪金高于公司平均薪金的所有员工,所在部门、上级领导、雇员的工资等级

相当的经典

第一步:求出薪金高于公司平均薪金的所有员工 

第二步:把第一步的结果当成临时表t 将临时表t和部门表 dept d 和工资等级表salary s进行关联,求出员工所在的部门,雇员的工资等级等

关联的条件是t.deptno = d.deptno  t.salary betweent s.lower and high;

第三步:求出第一步条件下的所有的上级领导,因为有的员工没有上级领导需要使用left join 左连接

第一步:求出公司的平均薪水
select avg(sal) as avgsal from emp;
+-------------+
| avgsal      |
+-------------+
| 2073.214286 |
+-------------+

select 
    d.dname,
    e.ename,
    b.ename as leadername,
    s.grade
from
    emp e
join
    dept d
on
    e.deptno = d.deptno
left join
    emp b
on
    e.mgr = b.empno
join
    salgrade s
on
    e.sal between s.losal and s.hisal
where
    e.sal > (select avg(sal) as avgsal from emp);
+------------+-------+------------+-------+
| dname      | ename | leadername | grade |
+------------+-------+------------+-------+
| RESEARCH   | JONES | KING       |     4 |
| SALES      | BLAKE | KING       |     4 |
| ACCOUNTING | CLARK | KING       |     4 |
| RESEARCH   | SCOTT | JONES      |     4 |
| ACCOUNTING | KING  | NULL       |     5 |
| RESEARCH   | FORD  | JONES      |     4 |
+------------+-------+------------+-------+
23.列出与“SCOTT”从事相同工作的所有员工及部门名称
查询出SCOTT的工作岗位
select job from emp where ename = 'SCOTT';
+---------+
| job     |
+---------+
| ANALYST |
+---------+

select 
    d.dname,
    e.*
from
    emp e
join
    dept d
on
    e.deptno = d.deptno
where
    e.job = (select job from emp where ename = 'SCOTT');
+----------+-------+-------+---------+------+------------+---------+------+--------+
| dname    | EMPNO | ENAME | JOB     | MGR  | HIREDATE   | SAL     | COMM | DEPTNO |
+----------+-------+-------+---------+------+------------+---------+------+--------+
| RESEARCH |  7788 | SCOTT | ANALYST | 7566 | 1987-04-19 | 3000.00 | NULL |     20 |
| RESEARCH |  7902 | FORD  | ANALYST | 7566 | 1981-12-03 | 3000.00 | NULL |     20 |
+----------+-------+-------+---------+------+------------+---------+------+--------+

 

 

25.列出薪金高于在部门30工作的所有员工的薪金的员工姓名和薪金、部门名称
第一步:先找出部门30的最高薪水
select max(sal) as maxsal from emp where deptno = 30;
+---------+
| maxsal  |
+---------+
| 2850.00 |
+---------+

select 
    d.dname,
    e.ename,
    e.sal
from
    emp e
join
    dept d
on
    e.deptno = d.deptno
where
    e.sal > (select max(sal) as maxsal from emp where deptno = 30);
+------------+-------+---------+
| dname      | ename | sal     |
+------------+-------+---------+
| ACCOUNTING | KING  | 5000.00 |
| RESEARCH   | JONES | 2975.00 |
| RESEARCH   | SCOTT | 3000.00 |
| RESEARCH   | FORD  | 3000.00 |
+------------+-------+---------+

 

这个题很关键


26.列出在每个部门工作的员工数量、平均工资和平均服务期限

第一步:求出每个部门对应的所有员工,这里使用了右连接,保证显示所有的部门,但是有的部门不存在员工,但是也必须把所有的部门显示出来

第二步:在第一步的基础上求出所有员工的数量,这里因为有的部门员工是null,所有不能使用count(*),count(*)统计包含null,应该使用count(e.ename)

第三步:求出员工的平均工资,因为有的部门员工不存在,所以对应的工作也是null,这里需要null值做处理

用法说明

1
IFNULL(expr1,expr2)
如果 expr1 不是 NULL,IFNULL() 返回 expr1,否则它返回 expr2。

IFNULL()返回一个数字或字符串值,取决于它被使用的上下文环境。

第四步:

mysql> SELECT TO_DAYS(950501);
+---------------------------------------------------------+
| TO_DAYS(950501) |
+---------------------------------------------------------+
| 728779 |
+---------------------------------------------------------+
1 row in set (0.00 sec)

我们来看下面的代码

动力节点 mysql 郭鑫 34道经典的面试题三

动力节点 mysql 郭鑫 34道经典的面试题三

动力节点 mysql 郭鑫 34道经典的面试题三

动力节点 mysql 郭鑫 34道经典的面试题三

动力节点 mysql 郭鑫 34道经典的面试题三

动力节点 mysql 郭鑫 34道经典的面试题三

 

 动力节点 mysql 郭鑫 34道经典的面试题三

ount(*)对行的数目进行计算,包含NULL
count(column)对特定的列的值具有的行数进行计算,不包含NULL值。

select count(*) from test2 ;
select count(id) from test2 ;
select count(name) from test2 ;
select count(name) from test2 where name is null;

 

当运行结果我们可以得出:3,3,2,0,为什么呢?让我来解释一下。首先count(1)指的并不是计算1的个数,而是指表的第一个字段,如果第一个字段没有建立索引,他的效率是很低的;而且count(column name)默认查询的是指定字段非空的个数,如果你想查询数据的所有行数,恰巧指定字段又是一个可存在空库数据的字段,那么得到的数据就不会是期望的值。再来说一下count(),在上述的count(column name)查询方式中,如果指定的column为限制为非空,那么mysql会将上述表达式转化为count()来进行查询。所以如果想要查询数据大小,在mysql中建议使用count(*)来执行,含义明了,速度还快。

同理:

28.列出所有部门的详细信息和人数

这里因为用到了左连接,同上面的题目,因为使用到了右连接可能存在null值,统计人数的时候不能使用count(*),而要使用count(e.ename)字段的值

select 
    d.deptno,d.dname,d.loc,count(e.ename) as totalEmp
from
    emp e
right join
    dept d
on
    e.deptno = d.deptno
group by
    d.deptno,d.dname,d.loc;
+--------+------------+----------+----------+
| deptno | dname      | loc      | totalEmp |
+--------+------------+----------+----------+
|     10 | ACCOUNTING | NEW YORK |        3 |
|     20 | RESEARCH   | DALLAS   |        5 |
|     30 | SALES      | CHICAGO  |        6 |
|     40 | OPERATIONS | BOSTON   |        0 |
+--------+------------+----------+----------+

 

29.列出各种工作的最低工资及从事此工作的雇员姓名

动力节点 mysql 郭鑫 34道经典的面试题三

动力节点 mysql 郭鑫 34道经典的面试题三

select 
    e.job,min(e.sal) as minsal
from
    emp e
group by 
    e.job;
+-----------+---------+
| job       | minsal  |
+-----------+---------+
| ANALYST   | 3000.00 |
| CLERK     |  800.00 |
| MANAGER   | 2450.00 |
| PRESIDENT | 5000.00 |
| SALESMAN  | 1250.00 |
+-----------+---------+

将以上查询结果当成临时表t(job,minsal)
select 
    e.ename
from
    emp e
join
    (select 
        e.job,min(e.sal) as minsal
    from
        emp e
    group by 
        e.job) t
on
    e.job = t.job
where
    e.sal = t.minsal;

+--------+
| ename  |
+--------+
| SMITH  |
| WARD   |
| MARTIN |
| CLARK  |
| SCOTT  |
| KING   |
| FORD   |
+--------+

 

动力节点 mysql 郭鑫 34道经典的面试题三

 

相关文章: