1. 程式人生 > 資料庫 >MySQL-34道經典查詢練習題(附帶答案及解析)

MySQL-34道經典查詢練習題(附帶答案及解析)

首先需要建立並初始化員工表、部門表、薪資等級表資料:

DROP TABLE IF EXISTS EMP;

DROP TABLE IF EXISTS DEPT;

DROP TABLE IF EXISTS SALGRADE;

CREATE TABLE DEPT (
	DEPTNO int(2) NOT NULL,
	DNAME VARCHAR(14),
	LOC VARCHAR(13),
	PRIMARY KEY (DEPTNO)
);

CREATE TABLE EMP (
	EMPNO int(4) NOT NULL,
	ENAME VARCHAR(10),
	JOB VARCHAR(9),
	MGR INT(4),
	HIREDATE DATE DEFAULT NULL,
	SAL DOUBLE(7, 2),
	COMM DOUBLE(7, 2),
	PRIMARY KEY (EMPNO),
	DEPTNO INT(2)
);

CREATE TABLE SALGRADE (
	GRADE INT,
	LOSAL INT,
	HISAL INT
);

INSERT INTO DEPT (DEPTNO, DNAME, LOC)
VALUES (10, 'ACCOUNTING', 'NEW YORK');

INSERT INTO DEPT (DEPTNO, DNAME, LOC)
VALUES (20, 'RESEARCH', 'DALLAS');

INSERT INTO DEPT (DEPTNO, DNAME, LOC)
VALUES (30, 'SALES', 'CHICAGO');

INSERT INTO DEPT (DEPTNO, DNAME, LOC)
VALUES (40, 'OPERATIONS', 'BOSTON');

COMMIT;

INSERT INTO EMP (EMPNO, ENAME, JOB, MGR, HIREDATE
	, SAL, COMM, DEPTNO)
VALUES (7369, 'SMITH', 'CLERK', 7902, '1980-12-17'
	, 800, NULL, 20);

INSERT INTO EMP (EMPNO, ENAME, JOB, MGR, HIREDATE
	, SAL, COMM, DEPTNO)
VALUES (7499, 'ALLEN', 'SALESMAN', 7698, '1981-02-20'
	, 1600, 300, 30);

INSERT INTO EMP (EMPNO, ENAME, JOB, MGR, HIREDATE
	, SAL, COMM, DEPTNO)
VALUES (7521, 'WARD', 'SALESMAN', 7698, '1981-02-22'
	, 1250, 500, 30);

INSERT INTO EMP (EMPNO, ENAME, JOB, MGR, HIREDATE
	, SAL, COMM, DEPTNO)
VALUES (7566, 'JONES', 'MANAGER', 7839, '1981-04-02'
	, 2975, NULL, 20);

INSERT INTO EMP (EMPNO, ENAME, JOB, MGR, HIREDATE
	, SAL, COMM, DEPTNO)
VALUES (7654, 'MARTIN', 'SALESMAN', 7698, '1981-09-28'
	, 1250, 1400, 30);

INSERT INTO EMP (EMPNO, ENAME, JOB, MGR, HIREDATE
	, SAL, COMM, DEPTNO)
VALUES (7698, 'BLAKE', 'MANAGER', 7839, '1981-05-01'
	, 2850, NULL, 30);

INSERT INTO EMP (EMPNO, ENAME, JOB, MGR, HIREDATE
	, SAL, COMM, DEPTNO)
VALUES (7782, 'CLARK', 'MANAGER', 7839, '1981-06-09'
	, 2450, NULL, 10);

INSERT INTO EMP (EMPNO, ENAME, JOB, MGR, HIREDATE
	, SAL, COMM, DEPTNO)
VALUES (7788, 'SCOTT', 'ANALYST', 7566, '1987-04-19'
	, 3000, NULL, 20);

INSERT INTO EMP (EMPNO, ENAME, JOB, MGR, HIREDATE
	, SAL, COMM, DEPTNO)
VALUES (7839, 'KING', 'PRESIDENT', NULL, '1981-11-17'
	, 5000, NULL, 10);

INSERT INTO EMP (EMPNO, ENAME, JOB, MGR, HIREDATE
	, SAL, COMM, DEPTNO)
VALUES (7844, 'TURNER', 'SALESMAN', 7698, '1981-09-08'
	, 1500, 0, 30);

INSERT INTO EMP (EMPNO, ENAME, JOB, MGR, HIREDATE
	, SAL, COMM, DEPTNO)
VALUES (7876, 'ADAMS', 'CLERK', 7788, '1987-05-23'
	, 1100, NULL, 20);

INSERT INTO EMP (EMPNO, ENAME, JOB, MGR, HIREDATE
	, SAL, COMM, DEPTNO)
VALUES (7900, 'JAMES', 'CLERK', 7698, '1981-12-03'
	, 950, NULL, 30);

INSERT INTO EMP (EMPNO, ENAME, JOB, MGR, HIREDATE
	, SAL, COMM, DEPTNO)
VALUES (7902, 'FORD', 'ANALYST', 7566, '1981-12-03'
	, 3000, NULL, 20);

INSERT INTO EMP (EMPNO, ENAME, JOB, MGR, HIREDATE
	, SAL, COMM, DEPTNO)
VALUES (7934, 'MILLER', 'CLERK', 7782, '1982-01-23'
	, 1300, NULL, 10);

COMMIT;

INSERT INTO SALGRADE (GRADE, LOSAL, HISAL)
VALUES (1, 700, 1200);

INSERT INTO SALGRADE (GRADE, LOSAL, HISAL)
VALUES (2, 1201, 1400);

INSERT INTO SALGRADE (GRADE, LOSAL, HISAL)
VALUES (3, 1401, 2000);

INSERT INTO SALGRADE (GRADE, LOSAL, HISAL)
VALUES (4, 2001, 3000);

INSERT INTO SALGRADE (GRADE, LOSAL, HISAL)
VALUES (5, 3001, 9999);

COMMIT;

SELECT *
FROM emp;

SELECT *
FROM dept;

SELECT *
FROM salgrade;
員工表:

部門表:

薪資等級表:

1. 取得每個部門最高薪水的人員名稱

  先取得部門最高薪水:
  select deptno,max(sal) from emp group  by deptno;    

  最終查詢語句及結果:                                                                                                
  select e.ename,t.* from (select deptno,max(sal) maxsal from emp group by deptno)  t  join emp e on t.deptno = e.deptno and t.maxsal = e.sal;
  +-------+--------+---------+
  | ename | deptno | maxsal  |
  +-------+--------+---------+
  | BLAKE |     30 | 2850.00 |
  | SCOTT |     20 | 3000.00 |
  | KING  |     10 | 5000.00 |
  | FORD  |     20 | 3000.00 |
  +-------+--------+---------+

2. 哪些人的薪水在部門平均薪水之上

  先取得部門平均薪水:
  select deptno,avg(sal) avgsal from emp group by deptno;

  最終查詢語句及結果:   
  select e1.ename,e1.sal,e1.deptno from emp e1 join (select deptno,avg(sal) avgsal from emp group by deptno) e2 on e1. deptno = e2.deptno  where e1.sal > e2.avgsal order by deptno; 
  +-------+---------+--------+
  | ename | sal     | deptno |
  +-------+---------+--------+
  | KING  | 5000.00 |     10 |
  | JONES | 2975.00 |     20 |
  | SCOTT | 3000.00 |     20 |
  | FORD  | 3000.00 |     20 |
  | ALLEN | 1600.00 |     30 |
  | BLAKE | 2850.00 |     30 |
  +-------+---------+--------+

3. 取得部門中(所有人)平均薪水等級

  先取得所有人的薪水等級:
  select e.*,s.grade from emp e join salgrade s on e.sal between s.losal and hisal;

  最終查詢語句及結果:   
  select t.deptno,avg(t.grade) avgsalgrade from (select e.*,s.grade from emp e join salgrade s on e.sal between s.losal and hisal) t group by t.deptno;
  +--------+-------------+
  | DEPTNO | avgsalgrade |
  +--------+-------------+
  |     10 |      3.6667 |
  |     20 |      2.8000 |
  |     30 |      2.5000 |
  +--------+-------------+

4. 不準用組函式(max),取得最高薪水(給出兩種解決方案)

  第一種解決方案:
  根據降序後取第一條記錄:                                                                                                                                                                          
  select ename,sal from emp order by sal desc limit 1;

  第二種解決方案:
  自連線:其中一個值不小於任何一個值,distinct去重後使用not in 過濾查詢結果後即為最大值:
  select ename,sal from emp where sal not in (select distinct a.sal from emp a join emp b on a.sal < b.sal);
  +-------+---------+
  | ename | sal     |
  +-------+---------+
  | KING  | 5000.00 |
  +-------+---------+

5. 取得平均薪水最高的部門的部門編號

  第一種方案:
  先取得部門的平均薪水後降序排序取第一條資料:
  select deptno,avg(sal) avgsal from emp group by deptno order by avgsal desc limit 1;
  +--------+-------------+
  | deptno | avgsal      |
  +--------+-------------+
  |     10 | 2916.666667 |
  +--------+-------------+

  第二種方案:
  先取得每個部門的平均薪水:
  select avg(sal) avgsal from emp group by deptno;

  再將上面的查詢結果當做臨時表使用max分組函式取得最大值和部門編號:
  select t.deptno, max(t.avgsal) maxavgsal from (select deptno,avg(sal) avgsal from emp group by deptno) t;
  +--------+-------------+
  | deptno | maxavgsal   |
  +--------+-------------+
  |     10 | 2916.666667 |
  +--------+-------------+

6. 取得平均薪水最高的部門的部門名稱

  先取得每個部門的平均薪水:
  select avg(sal) avgsal from emp group by deptno;

  再將上面的查詢結果當做臨時表使用max分組函式取得最大值和部門編號:
  select t.deptno, max(t.avgsal) maxavgsal from (select deptno,avg(sal) avgsal from emp group by deptno) t;

  最後將該表與部門表連線後查詢出部門名稱:
  select t.deptno,d.dname, max(t.avgsal) maxavgsal from (select deptno,avg(sal) avgsal from emp group by deptno) t join dept d on t.deptno = d.deptno;
  +--------+------------+-------------+
  | deptno | dname      | maxavgsal   |
  +--------+------------+-------------+
  |     10 | ACCOUNTING | 2916.666667 |
  +--------+------------+-------------+

7. 求平均薪水的等級最低的部門的部門名稱

  先求出每個部門平均薪水:
  select deptno,avg(sal) avgsal from emp group by deptno;

  再求出每個部門平均薪水的等級:
  select t.deptno,s.grade  from (select deptno,avg(sal) avgsal from emp group by deptno) t join salgrade s on t.avgsal between s.losal and hisal;

  最後將查詢出來的資料當做一張臨時表與部門表連表查詢出部門名稱:
  select t1.deptno,d.dname,t1.grade from (select t.deptno,s.grade  from (select deptno,avg(sal) avgsal from emp group by deptno) t join salgrade s on t.avgsal between s.losal and hisal) t1 join dept d on t1.deptno = d.deptno;
  +--------+------------+-------+
  | deptno | dname      | grade |
  +--------+------------+-------+
  |     10 | ACCOUNTING |     4 |
  |     20 | RESEARCH   |     4 |
  |     30 | SALES      |     3 |
  +--------+------------+-------+

8. 取得比普通員工(員工程式碼沒有在mgr上出現的)的最高薪水還要高的經理人姓名

  先取得所有普通員工的最高薪水(共8個):
  select max(e.sal) maxsal from emp e where ename not in (select e.ename from emp e join emp e1 on e.empno = e1.mgr);

  最終查詢語句及結果:
  select ename from emp where sal > (select max(e.sal) maxsal from emp e where ename not in (select e.ename from emp e join emp e1 on e.empno = e1.mgr));
  +-------+
  | ename |
  +-------+
  | JONES |
  | BLAKE |
  | CLARK |
  | SCOTT |
  | KING  |
  | FORD  |
  +-------+

9. 取得薪水最高的前五名員工

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

10. 取得薪水最高的第六到第十名員工

  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 |   0.00 |     30 |
  |  7934 | MILLER | CLERK    | 7782 | 1982-01-23 | 1300.00 |   NULL |     10 |
  |  7521 | WARD   | SALESMAN | 7698 | 1981-02-22 | 1250.00 | 500.00 |     30 |
  +-------+--------+----------+------+------------+---------+--------+--------+

11. 取得最後入職的5名員工

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

12. 取得每個薪水等級有多少員工

  select s.grade,count(1) count from emp e join salgrade s on e.sal between s.losal and s.hisal group by grade;
  +-------+-------+
  | grade | count |
  +-------+-------+
  |     1 |     3 |
  |     2 |     3 |
  |     3 |     2 |
  |     4 |     5 |
  |     5 |     1 |
  +-------+-------+

13. 面試題

  有3個表S(學生表),C(課程表),SC(學生選課表)
  S(SNO,SNAME)代表(學號,姓名) 
  C(CNO,CNAME,CTEACHER)代表(課號,課名,教師)
  SC(SNO,CNO,SCGRADE)代表(學號,課號,成績) 
首先需要建立並初始化學生表、課程表、學生選課表資料:
  DROP TABLE IF EXISTS S;
  create table s(
        sno int(10) primary key auto_increment,
        sname varchar(32)
        );

  DROP TABLE IF EXISTS C;
  create table c(
        cno int(10) primary key auto_increment,
        cname varchar(32),
        cteacher varchar(32)
        );

  // sno+cno是複合主鍵,主鍵叧有一個
  // sno也是外來鍵,cno也是外來鍵,外來鍵有兩個
  DROP TABLE IF EXISTS SC;
  create table sc(
        sno int(10),
    cno int(10),
        scgrade double(3,1),
        constraint sc_sno_cno_pk primary key(sno,cno), 
        constraint sc_sno_fk foreign key(sno) references s(sno),
        constraint sc_cno_fk foreign key(cno) references c(cno)
        );

  INSERT INTO S ( SNO, SNAME ) VALUES ( '1', '學生1'); 
  INSERT INTO S ( SNO, SNAME ) VALUES ( '2', '學生2'); 
  INSERT INTO S ( SNO, SNAME ) VALUES ( '3', '學生3'); 
  INSERT INTO S ( SNO, SNAME ) VALUES ( '4', '學生4'); 
  commit;

  INSERT INTO C ( CNO, CNAME, CTEACHER ) VALUES ( '1', 'Java', '王老師'); 
  INSERT INTO C ( CNO, CNAME, CTEACHER ) VALUES ( '2', 'C++', '張老師'); 
  INSERT INTO C ( CNO, CNAME, CTEACHER ) VALUES ( '3', 'C#', '李老師'); 
  INSERT INTO C ( CNO, CNAME, CTEACHER ) VALUES ( '4', 'MySQL', '趙老師'); 
  INSERT INTO C ( CNO, CNAME, CTEACHER ) VALUES ( '5', 'Oracle', '黎明'); 
  commit;

  INSERT INTO SC ( SNO, CNO, SCGRADE ) VALUES ( '1', '1', '50'); 
  INSERT INTO SC ( SNO, CNO, SCGRADE ) VALUES ( '1', '2', '50'); 
  INSERT INTO SC ( SNO, CNO, SCGRADE ) VALUES ( '1', '3', '50'); 
  INSERT INTO SC ( SNO, CNO, SCGRADE ) VALUES ( '2', '2', '80');
  INSERT INTO SC ( SNO, CNO, SCGRADE ) VALUES ( '2', '3', '70');  
  INSERT INTO SC ( SNO, CNO, SCGRADE ) VALUES ( '2', '4', '59'); 
  INSERT INTO SC ( SNO, CNO, SCGRADE ) VALUES ( '3', '1', '60'); 
  INSERT INTO SC ( SNO, CNO, SCGRADE ) VALUES ( '3', '2', '61'); 
  INSERT INTO SC ( SNO, CNO, SCGRADE ) VALUES ( '3', '3', '99'); 
  INSERT INTO SC ( SNO, CNO, SCGRADE ) VALUES ( '3', '4', '100'); 
  INSERT INTO SC ( SNO, CNO, SCGRADE ) VALUES ( '3', '5', '52'); 
  INSERT INTO SC ( SNO, CNO, SCGRADE ) VALUES ( '4', '3', '82'); 
  INSERT INTO SC ( SNO, CNO, SCGRADE ) VALUES ( '4', '4', '99'); 
  INSERT INTO SC ( SNO, CNO, SCGRADE ) VALUES ( '4', '5', '40'); 
  commit;

  SELECT * FROM S;
  SELECT * FROM C;
  SELECT * FROM SC;
S 學生表:

C 課程表:

SC 學生選課表:

13-1. 找出沒選過“黎明”老師的所有學生姓名?

  先找出黎明老師的課程號:
  select cno from c where cteacher = '黎明';

  再通過課程號找出選修了該課程的學號:
  select sno from sc where cno = (select cno from c where cteacher = '黎明');

  最後過濾掉選擇了黎明老師課程的學生:
  select sname from s where sno not in (select sno from sc where cno = (select cno from c where cteacher = '黎明'));
  +---------+
  | sname   |
  +---------+
  | 學生1   |
  | 學生2   |
  +---------+

13-2. 列出2門以上(含2門)不及格學生姓名及平均成績

  先通過學號分組取得2門以上不及格學生的學號及平均成績:
  select sno,avg(scgrade) avggrade,count(1) count from sc where scgrade < 60 group by sno having count >=2;

  再通過學號連表查詢出學生姓名及平均成績:
  select  s.sname,t.avggrade from s s join (select sno,avg(scgrade) avggrade,count(1) count from sc where scgrade < 60 group by sno having count >=2) t on s.sno = t.sno;
  +---------+----------+
  | sname   | avggrade |
  +---------+----------+
  | 學生1   |       50 |
  +---------+----------+

13-3. 既學過1號課程又學過2號課所有學生的姓名

  先取得學過課程1和2的學號:
  select sno from sc where cno = 1 and 2;

  最終查詢語句及結果:
  select s.sname from s s join (select sno from sc where cno = 1 and 2) t on s.sno = t.sno;
  +---------+
  | sname   |
  +---------+
  | 學生1   |
  | 學生3   |
  +---------+

14. 列出所有員工及領導的名字

  select e.ename,e1.ename leadername from emp e left join emp e1 on e.mgr = e1.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      |
  +--------+------------+

15. 列出受僱日期早於其直接上級的所有員工編號、姓名、部門名稱

  先列出受僱日期遭遇其直接上級的員工編號、姓名、部門編號:
  select e.empno, e.ename,e.deptno,e.hiredate,e1.ename leadername,e1.hiredate from emp e left join emp e1 on e.mgr = e1.empno where e.hiredate < e1.hiredate;
  +-------+-------+--------+------------+------------+------------+
  | empno | ename | deptno | hiredate   | leadername | hiredate   |
  +-------+-------+--------+------------+------------+------------+
  |  7369 | SMITH |     20 | 1980-12-17 | FORD       | 1981-12-03 |
  |  7499 | ALLEN |     30 | 1981-02-20 | BLAKE      | 1981-05-01 |
  |  7521 | WARD  |     30 | 1981-02-22 | BLAKE      | 1981-05-01 |
  |  7566 | JONES |     20 | 1981-04-02 | KING       | 1981-11-17 |
  |  7698 | BLAKE |     30 | 1981-05-01 | KING       | 1981-11-17 |
  |  7782 | CLARK |     10 | 1981-06-09 | KING       | 1981-11-17 |
  +-------+-------+--------+------------+------------+------------+

  最終查詢語句及結果:
  select t.empno,t.ename,d.dname from (select e.empno, e.ename,e.deptno,e1.ename leadername from emp e left join emp e1 on e.mgr = e1.empno where e.hiredate < e1.hiredate) t join dept d on t.deptno = d.deptno;
  +-------+-------+------------+
  | empno | ename | dname      |
  +-------+-------+------------+
  |  7369 | SMITH | RESEARCH   |
  |  7499 | ALLEN | SALES      |
  |  7521 | WARD  | SALES      |
  |  7566 | JONES | RESEARCH   |
  |  7698 | BLAKE | SALES      |
  |  7782 | CLARK | ACCOUNTING |
  +-------+-------+------------+

16. 列出部門名稱和這些部門的員工資訊,同時列出那些沒有員工的部門

  select d.deptno,d.dname,e.* from emp e right join dept d on e.deptno = d.deptno order by d.deptno;
  +--------+------------+-------+--------+-----------+------+------------+---------+---------+--------+
  | deptno | dname      | EMPNO | ENAME  | JOB       | MGR  | HIREDATE   | SAL     | COMM    | DEPTNO |
  +--------+------------+-------+--------+-----------+------+------------+---------+---------+--------+
  |     10 | ACCOUNTING |  7934 | MILLER | CLERK     | 7782 | 1982-01-23 | 1300.00 |    NULL |     10 |
  |     10 | ACCOUNTING |  7782 | CLARK  | MANAGER   | 7839 | 1981-06-09 | 2450.00 |    NULL |     10 |
  |     10 | ACCOUNTING |  7839 | KING   | PRESIDENT | NULL | 1981-11-17 | 5000.00 |    NULL |     10 |
  |     20 | RESEARCH   |  7876 | ADAMS  | CLERK     | 7788 | 1987-05-23 | 1100.00 |    NULL |     20 |
  |     20 | RESEARCH   |  7566 | JONES  | MANAGER   | 7839 | 1981-04-02 | 2975.00 |    NULL |     20 |
  |     20 | RESEARCH   |  7902 | FORD   | ANALYST   | 7566 | 1981-12-03 | 3000.00 |    NULL |     20 |
  |     20 | RESEARCH   |  7788 | SCOTT  | ANALYST   | 7566 | 1987-04-19 | 3000.00 |    NULL |     20 |
  |     20 | RESEARCH   |  7369 | SMITH  | CLERK     | 7902 | 1980-12-17 |  800.00 |    NULL |     20 |
  |     30 | SALES      |  7499 | ALLEN  | SALESMAN  | 7698 | 1981-02-20 | 1600.00 |  300.00 |     30 |
  |     30 | SALES      |  7698 | BLAKE  | MANAGER   | 7839 | 1981-05-01 | 2850.00 |    NULL |     30 |
  |     30 | SALES      |  7844 | TURNER | SALESMAN  | 7698 | 1981-09-08 | 1500.00 |    0.00 |     30 |
  |     30 | SALES      |  7521 | WARD   | SALESMAN  | 7698 | 1981-02-22 | 1250.00 |  500.00 |     30 |
  |     30 | SALES      |  7900 | JAMES  | CLERK     | 7698 | 1981-12-03 |  950.00 |    NULL |     30 |
  |     30 | SALES      |  7654 | MARTIN | SALESMAN  | 7698 | 1981-09-28 | 1250.00 | 1400.00 |     30 |
  |     40 | OPERATIONS |  NULL | NULL   | NULL      | NULL | NULL       |    NULL |    NULL |   NULL |
  +--------+------------+-------+--------+-----------+------+------------+---------+---------+--------+

17. 列出至少有5個員工的所有部門

  select deptno, count(1) counter from emp group by deptno having counter >= 5;
  +--------+---------+
  | deptno | counter |
  +--------+---------+
  |     20 |       5 |
  |     30 |       6 |
  +--------+---------+

18. 列出薪水比“SMITH”多的所有員工資訊

  先查出‘SMTH’的薪水:
  select sal from emp where ename = 'SMITH';

  最終查詢語句及結果:
  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.00 |  300.00 |     30 |
  |  7521 | WARD   | SALESMAN  | 7698 | 1981-02-22 | 1250.00 |  500.00 |     30 |
  |  7566 | JONES  | MANAGER   | 7839 | 1981-04-02 | 2975.00 |    NULL |     20 |
  |  7654 | MARTIN | SALESMAN  | 7698 | 1981-09-28 | 1250.00 | 1400.00 |     30 |
  |  7698 | BLAKE  | MANAGER   | 7839 | 1981-05-01 | 2850.00 |    NULL |     30 |
  |  7782 | CLARK  | MANAGER   | 7839 | 1981-06-09 | 2450.00 |    NULL |     10 |
  |  7788 | SCOTT  | ANALYST   | 7566 | 1987-04-19 | 3000.00 |    NULL |     20 |
  |  7839 | KING   | PRESIDENT | NULL | 1981-11-17 | 5000.00 |    NULL |     10 |
  |  7844 | TURNER | SALESMAN  | 7698 | 1981-09-08 | 1500.00 |    0.00 |     30 |
  |  7876 | ADAMS  | CLERK     | 7788 | 1987-05-23 | 1100.00 |    NULL |     20 |
  |  7900 | JAMES  | CLERK     | 7698 | 1981-12-03 |  950.00 |    NULL |     30 |
  |  7902 | FORD   | ANALYST   | 7566 | 1981-12-03 | 3000.00 |    NULL |     20 |
  |  7934 | MILLER | CLERK     | 7782 | 1982-01-23 | 1300.00 |    NULL |     10 |
  +-------+--------+-----------+------+------------+---------+---------+--------+

19. 列出所有“CLERK”(辦事員)的姓名及其部門名稱,部門人數

  根據部門分組找出工作為“CLERK”的員工姓名及部門名稱:
  select e.ename,d.dname from emp e join dept d on e.deptno = d.deptno where job = 'CLERK';

  再找出每個部門的人數:
  select count(*) number from emp group by deptno;

  最後以上兩張表聯合查詢:
  select d1.ename,d1.dname,d2.number from (select e.deptno,e.ename,d.dname from emp e join dept d on e.deptno = d.deptno where job = 'CLERK') d1 join (select deptno,count(*) number from emp group by deptno) d2 on d1.deptno = d2.deptno;
  +--------+------------+--------+
  | ename  | dname      | number |
  +--------+------------+--------+
  | SMITH  | RESEARCH   |      5 |
  | ADAMS  | RESEARCH   |      5 |
  | JAMES  | SALES      |      6 |
  | MILLER | ACCOUNTING |      3 |
  +--------+------------+--------+

20. 列出最低薪水大於1500的各種工作及從事此工作的全部僱員人數

  select job,count(*) peoNumber from emp group by job having min(sal) > 1500;
  +-----------+-----------+
  | job       | peoNumber |
  +-----------+-----------+
  | ANALYST   |         2 |
  | MANAGER   |         3 |
  | PRESIDENT |         1 |
  +-----------+-----------+

21. 列出在部門“SALES”<銷售部>工作的員工的姓名,假定不知道銷售部門的部門編號

  先找出“SALES”<銷售部>的部門編號:
  select deptno from dept where dname = 'SALES';

  最後通過部門編號直接列出“SALES”部門工作的員工姓名:
  select ename from emp where deptno = (select deptno from dept where dname = 'SALES');
  +--------+
  | ename  |
  +--------+
  | ALLEN  |
  | WARD   |
  | MARTIN |
  | BLAKE  |
  | TURNER |
  | JAMES  |
  +--------+

22. 列出薪金高於公司平均薪金的所有員工,所在部門、上級領導、僱員的工資等級

  先找出薪金高於公司平均薪金的所有員工:
  select ename from emp where sal > (select avg(sal) avgsal from emp);

  再找出薪金高於公司平均薪金的所有員工,所在部門:
  select e.ename,d.dname from emp e join dept d on e.deptno = d.deptno where sal > (select avg(sal) avgsal from emp);

  然後找出薪金高於公司平均薪金的所有員工,所在部門、上級領導:
  select e1.ename,d.dname,e2.ename from emp e1 join dept d on e1.deptno = d.deptno left join emp e2 on e1.mgr = e2.empno where e1.sal > (select avg(sal) avgsal from emp);

  最後列出薪金高於公司平均薪金的所有員工,所在部門、上級領導、工資等級:
  select e1.ename,d.dname,e2.ename,s.grade from emp e1 join dept d on e1.deptno = d.deptno left join emp e2 on e1.mgr = e2.empno join salgrade s on e1.sal between s.losal and s.hisal where e1.sal > (select avg(sal) avgsal from emp);
  +-------+------------+-------+-------+
  | ename | dname      | ename | grade |
  +-------+------------+-------+-------+
  | JONES | RESEARCH   | KING  |     4 |
  | BLAKE | SALES      | KING  |     4 |
  | CLARK | ACCOUNTING | KING  |     4 |
  | SCOTT | RESEARCH   | JONES |     4 |
  | KING  | ACCOUNTING | NULL  |     5 |
  | FORD  | RESEARCH   | JONES |     4 |
  +-------+------------+-------+-------+

23. 列出與“SCOTT”從事相同工作的所有員工及部門名稱

  先找出與“SCOTT”從事相同工作的所有員工:
  select ename from emp where job = (select job from emp where ename = 'SCOTT');

  再聯合部門表找出與“SCOTT”從事相同工作的所有員工及部門名稱:
  select e.ename,d.dname from emp e join dept d on e.deptno = d.deptno where job = (select job from emp where ename = 'SCOTT') and ename <> 'SCOTT';
  +-------+----------+
  | ename | dname    |
  +-------+----------+
  | FORD  | RESEARCH |
  +-------+----------+

24. 列出薪金等於部門30中員工的薪金的其它員工的姓名和薪金

  先找出30部門中員工的薪金:
  select sal from emp where deptno = 30;

  最終查詢語句及結果:
  select ename,sal from emp where sal in (select sal from emp where deptno = 30) and deptno <> 30;
  Empty set (0.00 sec)

25. 列出薪金高於在部門30工作的所有員工的薪金的員工姓名和薪金、部門名稱

  先找出在30部門工作的所有員工中最高薪金:
  select max(sal) maxsal from emp where deptno = 30;

  再找出薪金高於以上薪金的員工姓名和薪金的員工:
  select ename,sal from emp where sal > (select max(sal) maxsal from emp where deptno = 30) and deptno <> 30;

  最後找出薪金高於在部門30工作的所有員工的薪金的員工姓名和薪金、部門名稱:
  select e.ename,e.sal,d.dname from emp e join dept d on e.deptno = d.deptno where e.sal > (select max(sal) maxsal from emp where deptno = 30) and e.deptno <> 30;
  +-------+---------+------------+
  | ename | sal     | dname      |
  +-------+---------+------------+
  | JONES | 2975.00 | RESEARCH   |
  | SCOTT | 3000.00 | RESEARCH   |
  | KING  | 5000.00 | ACCOUNTING |
  | FORD  | 3000.00 | RESEARCH   |
  +-------+---------+------------+

26. 列出在每個部門工作的員工數量、平均工資和平均服務期限(*)

  // 其中涉及的函式包括:ifnull(欄位,0)      datediff(now(),日期)      right join
  select d.deptno,ifnull(count(e.ename),0) peonumber,ifnull(avg(e.sal),0) avgsal,ifnull(avg(datediff(now(),e.hiredate)/365),0) servertime from emp e right join dept d on e.deptno = d.deptno group by e.deptno order by deptno;
  +--------+-----------+-------------+-------------+
  | deptno | peonumber | avgsal      | servertime  |
  +--------+-----------+-------------+-------------+
  |     10 |         3 | 2916.666667 | 39.21186667 |
  |     20 |         5 | 2175.000000 | 37.23890000 |
  |     30 |         6 | 1566.666667 | 39.51051667 |
  |     40 |         0 |    0.000000 |  0.00000000 |
  +--------+-----------+-------------+-------------+

27. 列出所有員工的姓名、部門名稱和工資

  select e.ename,d.dname,e.sal from emp e join dept d on e.deptno = d.deptno;
  +--------+------------+---------+
  | ename  | dname      | sal     |
  +--------+------------+---------+
  | SMITH  | RESEARCH   |  800.00 |
  | ALLEN  | SALES      | 1600.00 |
  | WARD   | SALES      | 1250.00 |
  | JONES  | RESEARCH   | 2975.00 |
  | MARTIN | SALES      | 1250.00 |
  | BLAKE  | SALES      | 2850.00 |
  | CLARK  | ACCOUNTING | 2450.00 |
  | SCOTT  | RESEARCH   | 3000.00 |
  | KING   | ACCOUNTING | 5000.00 |
  | TURNER | SALES      | 1500.00 |
  | ADAMS  | RESEARCH   | 1100.00 |
  | JAMES  | SALES      |  950.00 |
  | FORD   | RESEARCH   | 3000.00 |
  | MILLER | ACCOUNTING | 1300.00 |
  +--------+------------+---------+

28. 列出所有部門的詳細資訊和人數

  select d.*,count(e.ename) peoNumber from dept d left join emp e on d.deptno = e.deptno group by e.deptno order by d.deptno;
  +--------+------------+----------+-----------+
  | DEPTNO | DNAME      | LOC      | peoNumber |
  +--------+------------+----------+-----------+
  |     10 | ACCOUNTING | NEW YORK |         3 |
  |     20 | RESEARCH   | DALLAS   |         5 |
  |     30 | SALES      | CHICAGO  |         6 |
  |     40 | OPERATIONS | BOSTON   |         0 |
  +--------+------------+----------+-----------+

29. 列出各種工作的最低工資及從事此工作的僱員姓名

  先找出各種工作的最低工資:
  select job,min(sal) minSal from emp group by job;

  最終查詢語句及結果:
  select ename,job,sal from emp where sal in (select min(sal) minSal from emp group by job);
  +--------+-----------+---------+
  | ename  | job       | sal     |
  +--------+-----------+---------+
  | SMITH  | CLERK     |  800.00 |
  | WARD   | SALESMAN  | 1250.00 |
  | MARTIN | SALESMAN  | 1250.00 |
  | CLARK  | MANAGER   | 2450.00 |
  | SCOTT  | ANALYST   | 3000.00 |
  | KING   | PRESIDENT | 5000.00 |
  | FORD   | ANALYST   | 3000.00 |
  +--------+-----------+---------+

30. 列出各個部門MANAGER的最低薪金

  select deptno,min(sal) minSal from emp where job = 'MANAGER' group by deptno;
  +--------+---------+
  | deptno | minSal  |
  +--------+---------+
  |     10 | 2450.00 |
  |     20 | 2975.00 |
  |     30 | 2850.00 |
  +--------+---------+

31. 列出所有員工的年工資,按年薪從低到高掋序

  select ename,ifnull(sal,0) * 12 annualSal from emp order by annualSal;
  +--------+-----------+
  | ename  | annualSal |
  +--------+-----------+
  | SMITH  |   9600.00 |
  | JAMES  |  11400.00 |
  | ADAMS  |  13200.00 |
  | WARD   |  15000.00 |
  | MARTIN |  15000.00 |
  | MILLER |  15600.00 |
  | TURNER |  18000.00 |
  | ALLEN  |  19200.00 |
  | CLARK  |  29400.00 |
  | BLAKE  |  34200.00 |
  | JONES  |  35700.00 |
  | SCOTT  |  36000.00 |
  | FORD   |  36000.00 |
  | KING   |  60000.00 |
  +--------+-----------+

32. 求出員工領導的薪水超過3000的員工名稱和領導名稱

  select e1.ename,e2.ename,e2.sal from emp e1 join emp e2 on e1.mgr = e2.empno where e2.sal > 3000;
  +-------+-------+---------+
  | ename | ename | sal     |
  +-------+-------+---------+
  | JONES | KING  | 5000.00 |
  | BLAKE | KING  | 5000.00 |
  | CLARK | KING  | 5000.00 |
  +-------+-------+---------+

33. 求部門名稱中帶“S”字元的部門員工的工資合計、部門人數

  select d.dname,ifnull(sum(e.sal),0) sumSal,count(e.ename) peoNumber from emp e right join dept d on e.deptno = d.deptno where d.dname like '%S%' group by d.deptno;
  +------------+----------+-----------+
  | dname      | sumSal   | peoNumber |
  +------------+----------+-----------+
  | RESEARCH   | 10875.00 |         5 |
  | SALES      |  9400.00 |         6 |
  | OPERATIONS |     0.00 |         0 |
  +------------+----------+-----------+

34. 給任職日期超過30年的員工加薪10%

  找出任職日期超過30年的員工然後加薪10%:
  update emp set sal = sal * 1.1 where datediff(now(),hiredate)/365 > 30;

試題答案均已經過驗證,但試題由於本人所做,所以解決方案可能並非最優,如果有更好的調優方案可評論交流,謝謝(╹▽╹)!