zoukankan      html  css  js  c++  java
  • 动力节点 mysql 郭鑫 34道经典的面试题三

    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)

    我们来看下面的代码

     

    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.列出各种工作的最低工资及从事此工作的雇员姓名

    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   |
    +--------+

  • 相关阅读:
    Bean管理学习笔记
    Spring核心概念学习笔记
    Spring主要用到两种设计模式
    C# 值类型和引用类型等值判断
    嵌入式Linux之gdb配置和使用
    嵌入式Linux之telnet
    构建嵌入式Linux交叉编译工具链
    Linux动态库和静态库
    VxWorks BSP开发入门
    buildroot
  • 原文地址:https://www.cnblogs.com/kebibuluan/p/8397991.html
Copyright © 2011-2022 走看看