動力節點 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   |
+--------+

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM