面试必备的经典SQL语句大全

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_36520235/article/details/83065210

练习SQL语句大全(关键看思路)

该数据有三张表:
部门表dept(deptno部门编号、dname部门名称、loc位置)、
员工表emp(empno工号、ename员工姓名、job职位、mgr直属领导工号、hiredate入职日期、sal月薪、comm补贴、deptno部门编号)、
薪水等级表salgrade(grade等级、losal区间下限、hisal区间上限)

1、 取得每个部门最高薪水人员的名称

#1.先查每个部门最高薪水的(按照部门编号分组)
SELECT deptno ,MAX(sal) AS maxsal FROM emp GROUP BY deptno
#2.把这张表当做临时表,跟emp表进行连接通过员工表的部门编号和最高的薪水
SELECT emp.ename , t.*
FROM emp
JOIN (SELECT deptno ,MAX(sal) AS maxsal FROM emp GROUP BY deptno) as t
ON t.deptno = emp.deptno AND t.maxsal = emp.sal

2、 哪些人的薪水在部门平均薪水之上?

#第一步需要先按照部门编号分组选出每个部门的平均薪水
SELECT deptno , AVG(sal) FROM emp GROUP BY deptno
#第二步需要把刚才的那个表当做临时表通过临时表的部门id且当部门表中的薪水比临时表中的薪水高的时候查出所有的数据
SELECT emp.ename,emp.sal , t.*
FROM emp
JOIN (SELECT deptno , AVG(sal) AS avgsal FROM emp GROUP BY deptno)t
ON emp.deptno = t.deptno AND emp.sal > t.avgsal

±-------±--------±-------±------------+
| ename | sal | deptno | avgsal |
±-------±--------±-------±------------+
| 李四 | 1600.00 | 30 | 1566.666667 |
| 李武 | 2975.00 | 20 | 2175.000000 |
| 刘振 | 2850.00 | 30 | 1566.666667 |
| 爱丽丝 | 3000.00 | 20 | 2175.000000 |
| 哪吒 | 5000.00 | 10 | 2916.666667 |
| 猴子 | 3000.00 | 20 | 2175.000000 |
±-------±--------±-------±------------+

3、(1)取得部门中(所有人的)平均薪水的等级

#思路:其实就是让你把部门的平均薪水等级而且是按部门分组得到临时表,在用临时表的平均薪水放到薪水等级表中用between完成
#第一步所以我们的目的是要求平均薪水的等级,也就是求部门的平均薪水(按部门分)
SELECT deptno ,AVG(sal) FROM emp GROUP BY deptno
#第二步是用得到的上表进行在薪水等级表中进行用betwee和and关联一起
SELECT t.* , salgrade.grade
FROM (SELECT deptno ,AVG(sal) AS avgsal FROM emp GROUP BY deptno) AS t
JOIN salgrade
ON avgsal BETWEEN salgrade.losal AND salgrade.hisal

±-------±------------±------+
| deptno | avgsal | grade |
±-------±------------±------+
| 10 | 2916.666667 | 4 |
| 20 | 2175.000000 | 4 |
| 30 | 1566.666667 | 3 |
±-------±------------±------+

3、 (2)取得部门中(所有人的)平均的薪水等级

#思路:其实说白了就是求出每一个员工的薪水等级然后在按部门进行排序,然后再对部门编号进行分组在分组内进行求平均成绩的函数
#第一步先求出每一个员工的薪水等级
SELECT emp.ename,emp.sal,emp.deptno,salgrade.grade FROM emp JOIN salgrade ON
emp.sal BETWEEN salgrade.losal AND salgrade.hisal ORDER BY emp.deptno
#第二步就是在上一步的基础上进行进行按部门分组,并且对成绩等级进行求平均函数
SELECT emp.deptno AS deptno,AVG( salgrade.grade) AS avgsal
FROM emp
JOIN salgrade ON
emp.sal BETWEEN salgrade.losal AND salgrade.hisal
GROUP BY emp.deptno
±-------±-------+
| deptno | avgsal |
±-------±-------+
| 10 | 3.6667 |
| 20 | 2.8000 |
| 30 | 2.5000 |
±-------±-------+

5、 取得平均薪水最高的部门和部门编号(至少给出两种解决方案)

(1)思路:(这种是使用最容易想到的两表关联)其实就是查询平均薪水最高的部门和编号,这里没什么好解释的
#第一步需要先求出部门平均薪水最高的部门,然后当成一个临时表
SELECT ename,deptno,AVG(sal) AS avgsal FROM emp GROUP BY deptno
#第二步把你的临时表跟你想要拿到的部门名称和编号都关联起来,这里可以使用当部门编号相同的时候来进行关联
SELECT dept.dname,dept.deptno , MAX(t.avgsal)
FROM dept
JOIN (SELECT ename,deptno,AVG(sal) AS avgsal FROM emp GROUP BY deptno)AS t
ON dept.deptno = t.deptno

±-------------±-------±--------------+
| dname | deptno | MAX(t.avgsal) |
±-------------±-------±--------------+
| 后勤部门 | 10 | 2916.666667 |
±-------------±-------±--------------+

(2)思路:(这种是使用临时表和目的表可以使用where条件关联)也是通过部门编号,这里思路和上面那个俩表关联一样的思路
#第一步需要先求出部门平均薪水最高的部门,然后当成一个临时表
SELECT ename,deptno,AVG(sal) AS avgsal FROM emp GROUP BY deptno
#第二步把你的临时表跟你想要拿到的部门名称和编号都关联起来,这里还可以使用where来进行关联
SELECT dept.dname,dept.deptno , MAX(t.avgsal)
FROM dept ,(SELECT ename,deptno,AVG(sal) AS avgsal FROM emp GROUP BY deptno)AS t
WHERE dept.deptno = t.deptno

±-------------±-------±--------------+
| dname | deptno | MAX(t.avgsal) |
±-------------±-------±--------------+
| 后勤部门 | 10 | 2916.666667 |
±-------------±-------±--------------+
(3)方案实现就是按照平均薪水降序排列取第一个

#首先第一步你得先取到每一个部门的平均薪水
SELECT AVG( sal) ,deptno FROM emp GROUP BY deptno
#然后第二步取出平均薪水最高的那个部门(把它当成一个)
SELECT AVG( sal) AS avgsal FROM emp GROUP BY deptno ORDER BY avgsal desc LIMIT 1
#第三步其实就是在第一步的基础上用having取到平均薪水最高的那个部门
SELECT AVG( sal) ,deptno FROM emp
GROUP BY deptno
HAVING AVG( sal) = (SELECT AVG( sal) AS avgsal FROM emp GROUP BY deptno ORDER BY avgsal desc LIMIT 1)
±------------±-------+
| AVG( sal) | deptno |
±------------±-------+
| 2916.666667 | 10 |
±------------±-------+

6、 取得平均薪水最高的部门和部门名称

#第一步先拿到每个部门的平均薪水
SELECT AVG(sal),deptno FROM emp GROUP BY deptno
#第二步先按照部门分组得出每个组的平均薪水,然后在排序取出最高的薪水
SELECT AVG(sal) AS avgsal FROM emp GROUP BY deptno ORDER BY avgsal DESC LIMIT 1
#第三步把取到的平均薪水最高的部门表当做临时表,和部门表进行关联,然后取出平均薪水最高的那个
SELECT dept.dname,avgsal
FROM (SELECT AVG(sal) AS avgsal ,deptno FROM emp GROUP BY deptno) AS t
JOIN dept
ON dept.deptno = t.deptno
HAVING avgsal =
(SELECT AVG(sal) AS avgsal FROM emp GROUP BY deptno ORDER BY avgsal DESC LIMIT 1)
±-------------±------------+
| dname | avgsal |
±-------------±------------+
| 后勤部门 | 2916.666667 |
±-------------±------------+

7、 求平均薪水的等级最高的部门的部门名称

#第一步先拿到各个部门的平均薪水的等级并且跟部门名称也进行关联一起
SELECT dept.dname,AVG(sal),emp.deptno FROM emp JOIN dept ON dept.deptno=emp.deptno GROUP BY deptno
#第二步通过第一步的临时表和薪水等级表进行关联,用临时表的平均薪水用between进行范围查询
SELECT t.dname,t.avgsal,s.grade
FROM (SELECT dept.dname AS dname,AVG(sal)AS avgsal,emp.deptno FROM emp JOIN dept ON dept.deptno=emp.deptno GROUP BY deptno) AS t
JOIN salgrade AS s
ON t.avgsal BETWEEN s.losal AND s.hisal
#第三步获取最高等级的值(首先你的想办法把平均薪水临时表和最高等级表进行关联起来)
SELECT MAX(grade)
FROM (SELECT AVG(sal) AS avgsal,deptno FROM emp GROUP BY deptno) AS t
JOIN salgrade AS s
ON t.avgsal BETWEEN s.losal AND s.hisal
#第四步其实就是把第二步和第三步进行联合一起进行查询,因为这里涉及到部门名称,
#所以需要在第一步的时候也要把部门名称和平均薪水关联起来

SELECT t.dname,t.avgsal,s.grade AS grade
FROM
(SELECT dept.dname AS dname,AVG(sal)AS avgsal,emp.deptno FROM emp JOIN dept ON dept.deptno=emp.deptno GROUP BY deptno) AS t
JOIN salgrade AS s
ON t.avgsal
BETWEEN s.losal AND s.hisal
WHERE grade = (SELECT MAX(grade)
FROM
(SELECT AVG(sal) AS avgsal,deptno FROM emp GROUP BY deptno) AS t
JOIN salgrade AS s
ON t.avgsal
BETWEEN s.losal AND s.hisal)

±-------------±------------±------+
| dname | avgsal | grade |
±-------------±------------±------+
| 后勤部门 | 2916.666667 | 4 |
| 开发部门 | 2175.000000 | 4 |
±-------------±------------±------+

8、 取得比普通员工(院代码没有在mgr字段出现的)的最高薪水还要高的领导人姓名

思路就是先取出全部的普通员工,然后用限定条件若不在直接领导人号的列表中就说明是普通员工,然后在取出员工最高的那个值当做一个字段和取出所有薪水的领导人进行where限定筛选
总结:在使用not in 的时候需要手动去除为NULL的字段的值,如果是使用in 的话可以自动忽略为NULL的字段值
#第一步首先是取出普通的员工(这里需要注意的是not in不会自动忽略空值,但是in可以)
SELECT * FROM emp WHERE empno not in
(SELECT DISTINCT mgr FROM emp WHERE mgr is NOT NULL)
#第二步找出普通员工的最高的薪水
SELECT MAX(sal) FROM emp WHERE empno not in
(SELECT DISTINCT mgr FROM emp WHERE mgr is NOT NULL)
#第三步需要找到比普通员工最高的薪水的领导人的姓名
SELECT emp.ename,sal FROM emp
WHERE sal >(SELECT MAX(sal) FROM emp WHERE empno not in
(SELECT DISTINCT mgr FROM emp WHERE mgr is NOT NULL))

±----------±--------+
| ename | sal |
±----------±--------+
| 李武 | 2975.00 |
| 刘振 | 2850.00 |
| 曹阳 | 2450.00 |
| 爱丽丝 | 3000.00 |
| 哪吒 | 5000.00 |
| 猴子 | 3000.00 |
±----------±--------+

9、 取得薪水最高的前五名员工

#这个没啥好说的就是直接查询然后按照薪水降序排序然后取到前5条数据
SELECT emp.ename,emp.sal FROM emp ORDER BY sal DESC LIMIT 5
±------±----------±----------±-----±-----------±--------±-----±-------+
| empno | ename | job | mgr | hiredate | sal | comm | deptno |
±------±----------±----------±-----±-----------±--------±-----±-------+
| 7839 | 哪吒 | PRESIDENT | NULL | 1981-11-17 | 5000.00 | NULL | 10 |
| 7902 | 猴子 | ANALYST | 7566 | 1981-12-03 | 3000.00 | NULL | 20 |
| 7788 | 爱丽丝 | ANALYST | 7566 | 1987-04-19 | 3000.00 | NULL | 20 |
| 7566 | 李武 | MANAGER | 7839 | 1981-04-02 | 2975.00 | NULL | 20 |
| 7698 | 刘振 | MANAGER | 7839 | 1981-05-01 | 2850.00 | NULL | 30 |
±------±----------±----------±-----±-----------±--------±-----±-------+

10、取得薪水最高的第六到第十名员工

#这个也没啥好说的主要是利用limit,也就是我们实现分页所需要用到的,
#limit的第一个数表示从第几条数据开始截取,第二个参数是从刚刚第一个参数开始截取多少条数据
SELECT * FROM emp ORDER BY sal DESC LIMIT 5, 5
±------±----------±---------±-----±-----------±--------±-------±-------+
| empno | ename | job | mgr | hiredate | sal | comm | deptno |
±------±----------±---------±-----±-----------±--------±-------±-------+
| 7782 | 曹阳 | MANAGER | 7839 | 1981-06-09 | 2450.00 | NULL | 10 |
| 7499 | 李四 | SALESMAN | 7698 | 1981-02-20 | 1600.00 | 300.00 | 30 |
| 7844 | 赵云 | SALESMAN | 7698 | 1981-09-08 | 1500.00 | NULL | 30 |
| 7934 | 安其拉 | CLERK | 7782 | 1982-01-23 | 1300.00 | NULL | 10 |
| 7521 | 王二 | SALESMAN | 7698 | 1981-02-22 | 1250.00 | 500.00 | 30 |
±------±----------±---------±-----±-----------±--------±-------±-------+

12、取得每个薪水等级有多少员工

思路:首先先按照薪水等级进行分组(这里需要考虑把员工表和薪水等级表进行关联),然后进行分组中的查询每个组的员工的个数
SELECT emp.*,COUNT(emp.empno)AS 每个等级的员工个数 FROM emp JOIN salgrade
ON sal BETWEEN salgrade.losal AND salgrade.hisal
GROUP BY salgrade.grade
±------±-------±----------±-----±-----------±--------±-------±-------±-----------------+
| empno | ename | job | mgr | hiredate | sal | comm | deptno | COUNT(emp.empno) |
±------±-------±----------±-----±-----------±--------±-------±-------±-----------------+
| 7369 | 张三 | CLERK | 7902 | 1980-12-17 | 800.00 | NULL | 20 | 3 |
| 7521 | 王二 | SALESMAN | 7698 | 1981-02-22 | 1250.00 | 500.00 | 30 | 3 |
| 7499 | 李四 | SALESMAN | 7698 | 1981-02-20 | 1600.00 | 300.00 | 30 | 2 |
| 7566 | 李武 | MANAGER | 7839 | 1981-04-02 | 2975.00 | NULL | 20 | 5 |
| 7839 | 哪吒 | PRESIDENT | NULL | 1981-11-17 | 5000.00 | NULL | 10 | 1 |
±------±-------±----------±-----±-----------±--------±-------±-------±-----------------+

14、列出所有员工及领导的姓名

#思路:就是因为员工和领导都在员工表中,但是他们的对应关系是员工表的上级是领导的员工号(因为领导也是员工啊)
SELECT a.ename AS ‘员工姓名’,b.ename AS ‘领导姓名’ FROM
emp AS a JOIN emp AS b
ON a.empno = b.mgr
±-------------±-------------+
| 员工姓名 | 领导姓名 |
±-------------±-------------+
| 猴子 | 张三 |
| 刘振 | 李四 |
| 刘振 | 王二 |
| 哪吒 | 李武 |
| 刘振 | 周六 |
| 哪吒 | 刘振 |
| 哪吒 | 曹阳 |
| 李武 | 爱丽丝 |
| 刘振 | 赵云 |
| 爱丽丝 | 妲己 |
| 刘振 | 刘备 |
| 李武 | 猴子 |
| 曹阳 | 安其拉 |
±-------------±-------------+

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

#第一步因为员工表中既有员工又有领导,那就让领导和员工表结合
#然后用where条件限定日期大小
#第二步是把部门表也给关联进去

SELECT a.empno AS ‘员工编号’,a.ename AS ‘员工姓名’,a.hiredate,
b.hiredate,b.empno AS ‘领导编号’,b.ename AS ‘领导姓名’,dept.dname AS ‘部门名称’
FROM emp AS a
JOIN emp AS b
ON a.empno = b.mgr
JOIN dept
ON a.deptno = dept.deptno
WHERE a.hiredate < b.hiredate

±-------------±-------------±-----------±-----------±-------------±-------------±-------------+
| 员工编号 | 员工姓名 | hiredate | hiredate | 领导编号 | 领导姓名 | 部门名称 |
±-------------±-------------±-----------±-----------±-------------±-------------±-------------+
| 7782 | 曹阳 | 1981-06-09 | 1982-01-23 | 7934 | 安其拉 | 后勤部门 |
| 7566 | 李武 | 1981-04-02 | 1987-04-19 | 7788 | 爱丽丝 | 开发部门 |
| 7788 | 爱丽丝 | 1987-04-19 | 1987-05-23 | 7876 | 妲己 | 开发部门 |
| 7566 | 李武 | 1981-04-02 | 1981-12-03 | 7902 | 猴子 | 开发部门 |
| 7698 | 刘振 | 1981-05-01 | 1981-09-28 | 7654 | 周六 | 销售部门 |
| 7698 | 刘振 | 1981-05-01 | 1981-09-08 | 7844 | 赵云 | 销售部门 |
| 7698 | 刘振 | 1981-05-01 | 1981-12-03 | 7900 | 刘备 | 销售部门 |
±-------------±-------------±-----------±-----------±-------------±-------------±-------------+

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

#思路:因为题目说了不仅要简单的列出部门名称和员工信息,而且还要列出部门里面没有员工的情况
#所以很容易能想到是用左联接,或者是右连接都可以实现
#(1)使用左连接实现
SELECT dname AS ‘部门名称’ , emp.* FROM dept LEFT JOIN emp
ON dept.deptno = emp.deptno ORDER BY dname
#(2)使用右连接实现
SELECT dept.dname , emp.* FROM emp RIGHT JOIN dept
ON dept.deptno = emp.deptno
±-------------±------±----------±----------±-----±-----------±--------±--------±-------+
| 部门名称 | empno | ename | job | mgr | hiredate | sal | comm | deptno |
±-------------±------±----------±----------±-----±-----------±--------±--------±-------+
| 后勤部门 | 7782 | 曹阳 | MANAGER | 7839 | 1981-06-09 | 2450.00 | NULL | 10 |
| 后勤部门 | 7839 | 哪吒 | PRESIDENT | NULL | 1981-11-17 | 5000.00 | NULL | 10 |
| 后勤部门 | 7934 | 安其拉 | CLERK | 7782 | 1982-01-23 | 1300.00 | NULL | 10 |
| 开发部门 | 7876 | 妲己 | CLERK | 7788 | 1987-05-23 | 1100.00 | NULL | 20 |
| 开发部门 | 7902 | 猴子 | ANALYST | 7566 | 1981-12-03 | 3000.00 | NULL | 20 |
| 开发部门 | 7566 | 李武 | MANAGER | 7839 | 1981-04-02 | 2975.00 | NULL | 20 |
| 开发部门 | 7788 | 爱丽丝 | ANALYST | 7566 | 1987-04-19 | 3000.00 | NULL | 20 |
| 开发部门 | 7369 | 张三 | CLERK | 7902 | 1980-12-17 | 800.00 | NULL | 20 |
| 推广部门 | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL |
| 销售部门 | 7499 | 李四 | SALESMAN | 7698 | 1981-02-20 | 1600.00 | 300.00 | 30 |
| 销售部门 | 7698 | 刘振 | MANAGER | 7839 | 1981-05-01 | 2850.00 | NULL | 30 |
| 销售部门 | 7844 | 赵云 | SALESMAN | 7698 | 1981-09-08 | 1500.00 | NULL | 30 |
| 销售部门 | 7900 | 刘备 | CLERK | 7698 | 1981-12-03 | 950.00 | NULL | 30 |
| 销售部门 | 7521 | 王二 | SALESMAN | 7698 | 1981-02-22 | 1250.00 | 500.00 | 30 |
| 销售部门 | 7654 | 周六 | SALESMAN | 7698 | 1981-09-28 | 1250.00 | 1400.00 | 30 |
±-------------±------±----------±----------±-----±-----------±--------±--------±-------+

17、列出至少有5个员工的所有部门的详细信息

#思路就是先把员工表和部门表进行关联,然后分组的时候之后只能用having,而且在使用分组的时候还可以是多个字段

SELECT emp.ename,dept.dname,dept.loc,dept.deptno
FROM emp
JOIN dept
ON emp.deptno = dept.deptno
GROUP BY dept.dname,dept.loc,dept.deptno
HAVING COUNT(emp.empno)>=5
±-------±-------------±--------±-------+
| ename | dname | loc | deptno |
±-------±-------------±--------±-------+
| 张三 | 开发部门 | DALLAS | 20 |
| 李四 | 销售部门 | CHICAGO | 30 |
±-------±-------------±--------±-------+

18、列出薪金比‘simith’多的所有员工信息

#先找出妲己的薪水,当做一个字段
SELECT emp.sal FROM emp WHERE ename=‘曹阳’
#然后找到全部的员工信息加个where条件语句把第一步找到的薪水还大的给找出来
SELECT emp.* FROM emp WHERE sal >=(SELECT emp.sal FROM emp WHERE ename=‘曹阳’)
±------±----------±----------±-----±-----------±--------±-----±-------+
| empno | ename | job | mgr | hiredate | sal | comm | deptno |
±------±----------±----------±-----±-----------±--------±-----±-------+
| 7566 | 李武 | MANAGER | 7839 | 1981-04-02 | 2975.00 | NULL | 20 |
| 7698 | 刘振 | MANAGER | 7839 | 1981-05-01 | 2850.00 | NULL | 30 |
| 7782 | 曹阳 | MANAGER | 7839 | 1981-06-09 | 2450.00 | NULL | 10 |
| 7788 | 爱丽丝 | ANALYST | 7566 | 1987-04-19 | 3000.00 | NULL | 20 |
| 7839 | 哪吒 | PRESIDENT | NULL | 1981-11-17 | 5000.00 | NULL | 10 |
| 7902 | 猴子 | ANALYST | 7566 | 1981-12-03 | 3000.00 | NULL | 20 |
±------±----------±----------±-----±-----------±--------±-----±-------+

19、列出所有’clerk’(办事员)的姓名及部门名称,部门人数

#第一步是先找出所有的“clerk”的姓名和部门名称作为一个表
SELECT e.ename,d.dname FROM emp AS e
JOIN dept AS d
ON d.deptno = e.deptno
WHERE job = ‘clerk’
#第二步是找出部门人数而且是按照部门编号进行分组
SELECT deptno , COUNT() AS total FROM emp GROUP BY deptno
#第三步是把第一步的表和第二步的表进行连接通过部门编号
SELECT e.ename,d.dname,t.total FROM emp AS e
JOIN dept AS d
ON d.deptno = e.deptno
JOIN (SELECT deptno , COUNT(
) AS total FROM emp GROUP BY deptno)AS t
ON t.deptno = e.deptno
WHERE job = ‘clerk’
±----------±-------------±------+
| ename | dname | total |
±----------±-------------±------+
| 张三 | 开发部门 | 5 |
| 妲己 | 开发部门 | 5 |
| 刘备 | 销售部门 | 6 |
| 安其拉 | 后勤部门 | 3 |
±----------±-------------±------+

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

(1)第一种方式答案
#第一步先按工作进行分组
SELECT job ,sal FROM emp GROUP BY job
#第二步然后找出工资最低的然后限定条件是大于1500
SELECT job, MIN(sal)AS minsal,COUNT()
FROM emp GROUP BY job HAVING minsal>1500
±----------±--------±---------+
| job | minsal | COUNT(
) |
±----------±--------±---------+
| ANALYST | 3000.00 | 2 |
| MANAGER | 2450.00 | 3 |
| PRESIDENT | 5000.00 | 1 |
±----------±--------±---------+

21、列出在部门‘开发部门’工作的员工的姓名,假定不知道开发部的部门编号

#第一步如果不知道开发部门的部门编号,但是我根据部门名称不是也可以查询部门编号吗
SELECT deptno FROM dept WHERE dname = ‘开发部门’
#第二步然后把查到的部门编号当做是一个字段,在进行去员工表中去查询
SELECT ename FROM emp
WHERE deptno = (SELECT deptno FROM dept WHERE dname = ‘开发部门’)
±----------+
| ename |
±----------+
| 张三 |
| 李武 |
| 爱丽丝 |
| 妲己 |
| 猴子 |
±----------+

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

#第一步是查出公司所有员工的平均工资
SELECT AVG(sal) FROM emp
#第二步还需要去查询上一级领导
SELECT a.ename AS ‘员工名称’,b.ename AS ‘领导的名字’
FROM emp AS a JOIN emp AS b ON a.empno = b.mgr

#第三步是需要把部门表和员工表和薪水等级表进行关联起来
SELECT a.sal ,b.ename,dept.dname ,salgrade.grade ,a.ename AS ‘上级领导’
FROM emp AS a JOIN dept ON a.deptno =dept.deptno
JOIN emp AS b ON a.empno = b.mgr
JOIN salgrade ON a.sal
BETWEEN salgrade.losal AND salgrade.hisal
WHERE a.sal > (SELECT AVG(emp.sal) FROM emp )
±--------±----------±-------------±------±-------------+
| sal | ename | dname | grade | 上级领导 |
±--------±----------±-------------±------±-------------+
| 3000.00 | 张三 | 开发部门 | 4 | 猴子 |
| 2850.00 | 李四 | 销售部门 | 4 | 刘振 |
| 2850.00 | 王二 | 销售部门 | 4 | 刘振 |
| 5000.00 | 李武 | 后勤部门 | 5 | 哪吒 |
| 2850.00 | 周六 | 销售部门 | 4 | 刘振 |
| 5000.00 | 刘振 | 后勤部门 | 5 | 哪吒 |
| 5000.00 | 曹阳 | 后勤部门 | 5 | 哪吒 |
| 2975.00 | 爱丽丝 | 开发部门 | 4 | 李武 |
| 2850.00 | 赵云 | 销售部门 | 4 | 刘振 |
| 3000.00 | 妲己 | 开发部门 | 4 | 爱丽丝 |
| 2850.00 | 刘备 | 销售部门 | 4 | 刘振 |
| 2975.00 | 猴子 | 开发部门 | 4 | 李武 |
| 2450.00 | 安其拉 | 后勤部门 | 4 | 曹阳 |
±--------±----------±-------------±------±-------------+

23、列出与‘妲己’从事相同工作的所有员工及部门名称

#第一步先找到和妲己同一个部门的部门编号,然后通过找到的这个部门编号再去查询素有的员工信息
SELECT dept.deptno FROM dept JOIN emp ON emp.deptno = dept.deptno WHERE emp.ename=‘妲己’
#第二步通过部门编号去找所有的员工信息
SELECT emp.ename, dept.dname
FROM emp JOIN dept ON emp.deptno=dept.deptno
WHERE dept.deptno=(SELECT dept.deptno FROM dept JOIN emp
ON emp.deptno = dept.deptno WHERE emp.ename=‘妲己’)
±----------±-------------+
| ename | dname |
±----------±-------------+
| 张三 | 开发部门 |
| 李武 | 开发部门 |
| 爱丽丝 | 开发部门 |
| 妲己 | 开发部门 |
| 猴子 | 开发部门 |
±----------±-------------+

24、列出薪金等于部门30中员工的薪金的其他员工的姓名和薪金

#第一步首先是先查出部们编号等于30的员工
SELECT DISTINCT sal FROM emp WHERE deptno = 30
#第二步是查询所有部门的员工的薪水在上一个SQL中,且部门编号不等于30的
SELECT ename,sal FROM emp WHERE sal
in(SELECT DISTINCT sal FROM emp WHERE deptno = 30) AND deptno != 30
±----------±-------+
| ename | sal |
±----------±-------+
| 安其拉 | 950.00 |
±----------±-------+

25、列出薪金高于在部门30工作的所有员工的薪金的员工姓名和薪金,部门名称

#第一步其实就是找出部门编号为30的员工的最高薪水
SELECT MAX(sal) FROM emp WHERE deptno = 30
#第二步就是把员工表和部门表联合然后薪水的条件大于上面的SQL语句的薪水
SELECT emp.ename,emp.sal,dept.dname FROM emp JOIN
dept ON emp.deptno=dept.deptno
WHERE sal > (SELECT MAX(sal) FROM emp WHERE deptno = 30)

±----------±--------±-------------+
| ename | sal | dname |
±----------±--------±-------------+
| 李武 | 2975.00 | 开发部门 |
| 爱丽丝 | 3000.00 | 开发部门 |
| 哪吒 | 5000.00 | 后勤部门 |
| 猴子 | 3000.00 | 开发部门 |
±----------±--------±-------------+

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

#第一步先按部门编号分组去找出平均工资和员工数量,因为有的部门是没有员工的
SELECT dept.deptno,COUNT(emp.ename),IFNULL(AVG(sal),0)AS ‘平均工资’ ,
IFNULL(((TO_DAYS(now())-TO_DAYS(emp.hiredate))/365),0) AS ‘平均服务期限’
FROM emp
RIGHT JOIN dept
ON emp.deptno=dept.deptno
GROUP BY dept.deptno
#总结:这里用到了ifNull(A,B)是用来判断如果A为空,就会把值设置为B
#TO_days(A)是把时间转换为天数的函数

±-------±-----------------±-------------±-------------------+
| deptno | COUNT(emp.ename) | 平均工资 | 平均服务期限 |
±-------±-----------------±-------------±-------------------+
| 10 | 3 | 2800.000000 | 37.4192 |
| 20 | 5 | 2175.000000 | 37.8959 |
| 30 | 6 | 1566.666667 | 37.7178 |
| 40 | 0 | 0.000000 | 0.0000 |
±-------±-----------------±-------------±-------------------+

27、列出所有员工的姓名、部门名称、工资

#这个有点太简单了直接就能写出来了
SELECT emp.ename,emp.sal ,dept.dname FROM emp JOIN dept ON emp.deptno=dept.deptno

±----------±--------±-------------+
| ename | sal | dname |
±----------±--------±-------------+
| 张三 | 800.00 | 开发部门 |
| 李四 | 1600.00 | 销售部门 |
| 王二 | 1250.00 | 销售部门 |
| 李武 | 2975.00 | 开发部门 |
| 周六 | 1250.00 | 销售部门 |
| 刘振 | 2850.00 | 销售部门 |
| 曹阳 | 2450.00 | 后勤部门 |
| 爱丽丝 | 3000.00 | 开发部门 |
| 哪吒 | 5000.00 | 后勤部门 |
| 赵云 | 1500.00 | 销售部门 |
| 妲己 | 1100.00 | 开发部门 |
| 刘备 | 950.00 | 销售部门 |
| 猴子 | 3000.00 | 开发部门 |
| 安其拉 | 950.00 | 后勤部门 |
±----------±--------±-------------+

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

#首先思路就是直接按照部门编号进行分组,然后对需要考虑到左联或者右联接
SELECT dept.* ,COUNT(emp.ename)AS ‘部门人数’ FROM dept LEFT JOIN emp ON emp.deptno=dept.deptno
GROUP BY dept.deptno
±-------±-------------±---------±-------------+
| deptno | dname | loc | 部门人数 |
±-------±-------------±---------±-------------+
| 10 | 后勤部门 | NEW YORK | 3 |
| 20 | 开发部门 | DALLAS | 5 |
| 30 | 销售部门 | CHICAGO | 6 |
| 40 | 推广部门 | BOSTON | 0 |
±-------±-------------±---------±-------------+

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

SELECT MIN(emp.sal),ename,job FROM emp GROUP BY job ORDER BY sal
±-------------±----------±----------+
| MIN(emp.sal) | ename | job |
±-------------±----------±----------+
| 800.00 | 张三 | CLERK |
| 1250.00 | 李四 | SALESMAN |
| 2450.00 | 李武 | MANAGER |
| 3000.00 | 爱丽丝 | ANALYST |
| 5000.00 | 哪吒 | PRESIDENT |
±-------------±----------±----------+

30、列出各个部门的manager的最低薪金

SELECT deptno,MIN(sal ) FROM emp WHERE job = ‘MANAGER’ GROUP BY deptno
±-------±----------+
| deptno | MIN(sal ) |
±-------±----------+
| 10 | 2450.00 |
| 20 | 2975.00 |
| 30 | 2850.00 |
±-------±----------+

31、列出员工的年工资,按年薪从低到高排序

SELECT (sal*12) AS total ,emp.ename FROM emp ORDER BY total
±---------±----------+
| total | ename |
±---------±----------+
| 9600.00 | 张三 |
| 11400.00 | 刘备 |
| 11400.00 | 安其拉 |
| 13200.00 | 妲己 |
| 15000.00 | 王二 |
| 15000.00 | 周六 |
| 18000.00 | 赵云 |
| 19200.00 | 李四 |
| 29400.00 | 曹阳 |
| 34200.00 | 刘振 |
| 35700.00 | 李武 |
| 36000.00 | 爱丽丝 |
| 36000.00 | 猴子 |
| 60000.00 | 哪吒 |
±---------±----------+

32、求出员工领导的薪水超过3000的员工名称与领导姓名

SELECT a.ename AS ‘员工名称’,b.ename AS ‘领导姓名’ ,b.sal
FROM emp AS a JOIN emp AS b ON a.mgr=b.empno WHERE b.sal>3000
±-------------±-------------±--------+
| 员工名称 | 领导姓名 | sal |
±-------------±-------------±--------+
| 李武 | 哪吒 | 5000.00 |
| 刘振 | 哪吒 | 5000.00 |
| 曹阳 | 哪吒 | 5000.00 |
±-------------±-------------±--------+

33、求出部门名称中,带有‘s’字符的部门员工的工资合计、部门人数

#第一步先把部门表和员工表进行连接,需要注意当部门编号为40的时候是没有员工的,
#然后按照员工编号进行分组
SELECT IFNULL(SUM(emp.sal),0),COUNT(emp.empno) FROM dept LEFT JOIN emp
ON dept.deptno=emp.deptno GROUP BY dept.deptno
#第二步因为说把含有“s”字符的部门员工都统计到,需要在上面的基础上加上like限定
SELECT dept.deptno, IFNULL(SUM(emp.sal),0),COUNT(emp.ename)
FROM dept LEFT JOIN emp
ON dept.deptno=emp.deptno
WHERE dept.dname LIKE ‘%部%’
GROUP BY dept.deptno
±-------±-----------------------±-----------------+
| deptno | IFNULL(SUM(emp.sal),0) | COUNT(emp.ename) |
±-------±-----------------------±-----------------+
| 10 | 8400.00 | 3 |
| 20 | 10875.00 | 5 |
| 30 | 9400.00 | 6 |
| 40 | 0.00 | 0 |
±-------±-----------------------±-----------------+

34、给任职日期超过35年的员工加薪10%

CREATE TABLE emp_bak AS SELECT * FROM emp

UPDATE emp_bak SET sal = sal*1.1
WHERE (TO_DAYS(NOW())-(TO_DAYS(hiredate)))/365 > 30

猜你喜欢

转载自blog.csdn.net/qq_36520235/article/details/83065210