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