sql语句练习--mysql
0. 开始
exam数据库的创建和使用:
|
|
表的创建:
|
|
表数据的插入:
|
|
查看表:
|
|
1. 练习
1.1 DQL练习
-
查询出部门编号为30的所有员工
- 列:没有说明要查询的列,所以查询所有列
- 表:只一张表,emp
- 条件:部门编号为30,即deptno=30
1
SELECT * FROM emp WHERE deptno=30;
-
所有销售员的姓名、编号和部门编号
- 列:姓名ename、编号empno、部门编号deptno
- 表:emp
- 条件:所有销售员,即job=‘销售员’
1
SELECT ename,empno,deptno FROM emp WHERE job='销售员'
-
找出奖金高于工资的员工
- 列:所有列
- 表:emp
- 条件:奖金>工资,即comm>sal
1
SELECT * FROM emp WHERE comm>sal;
-
找出奖金高于工资60%的员工
- 列:所有列
- 表:emp
- 条件:奖金>工资0.6,即comm>sal0.6
1
SELECT * FROM emp WHERE comm>sal*0.6;
-
找出部门编号为10中所有经理,和部门编号为20中所有销售员的详细资料
- 列:所有列
- 表:emp
- 条件:部门编号=10并且job为经理,和部门编号=20并且job为销售员
1
SELECT * FROM emp WHERE (deptno=10 AND job='经理') OR (deptno=20 AND job='销售员');
-
找出部门编号为10中所有经理,部门编号为20中所有销售员,还有即不是经理又不是销售员但其工资大或等于20000的所有员工详细资料
- 列:所有列
- 表:emp
- 条件:deptno=10 and job=‘经理’, depnto=20 and job=‘销售员’, job not in (‘销售员’,‘经理’) and sal>=20000
1 2 3 4 5
SELECT * FROM emp WHERE (deptno=10 AND job='经理') OR (deptno=20 AND job='销售员') OR job NOT IN ('经理','销售员') AND sal>=20000;
-
有奖金的工种
- 列:工作(不能重复出现)
- 表:emp
- 条件:comm is not null
1
SELECT DISTINCT job FROM emp WHERE comm IS NOT NULL;
-
无奖金或奖金低于1000的员工
- 列:所有列
- 表:emp
- 条件:comm is null 或者 comm < 1000
1
SELECT * FROM emp WHERE comm IS NULL OR comm < 1000;
-
查询名字由三个字组成的员工
- 列:所有
- 表:emp
- 条件:ename like ‘___’
1
SELECT * FROM emp WHERE ename LIKE '___'
-
查询2000年入职的员工
- 列:所有
- 表:emp
- 条件:hiredate like ‘2000%’
1 2 3
SELECT * FROM emp WHERE hiredate LIKE '2000%'; SELECT * FROM emp WHERE YEAR(hiredate) = '2000';
-
查询所有员工详细信息,用编号升序排序
- 列:所有
- 表:emp
- 条件:无
- 排序:empno asc
1
SELECT * FROM emp ORDER BY empno ASC;
-
查询所有员工详细信息,用工资降序排序,如果工资相同使用入职日期升序排序
- 列:所有
- 表:emp
- 条件:无
- 排序:sal desc, hiredate asc
1
SELECT * FROM emp ORDER BY sal DESC, hiredate ASC
-
查询每个部门的平均工资
- 列:部门编号、平均工资(平均工资就是分组信息)
- 表:emp
- 条件:无
- 分组:每个部门,即使用部门分组,平均工资,使用avg()函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14
SELECT deptno, AVG(sal) FROM emp GROUP BY deptno; SELECT d.dname, a AS '平均工资' FROM dept AS d, (SELECT deptno, AVG(sal) AS a FROM emp GROUP BY deptno) AS e WHERE d.deptno = e.deptno; SELECT dname, e.avg_sal FROM dept INNER JOIN (SELECT deptno, AVG(sal) AS avg_sal FROM emp GROUP BY deptno)AS e ON dept.deptno = e.deptno; SELECT d.`dname`, AVG(e.`sal`) AS '平均工资' FROM dept AS d RIGHT JOIN emp AS e ON d.`deptno`=e.`deptno` GROUP BY d.deptno;
-
求出每个部门的雇员数量
- 列:部门编号、人员数量(人员数量即记录数,这是分组信息)
- 表:emp
- 条件:无
- 分组:每个部门是分组信息,人员数量,使用count()函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
SELECT deptno, COUNT(1) FROM emp GROUP BY deptno; SELECT deptno, COUNT(*) FROM emp GROUP BY deptno; SELECT d.dname, _count AS '数量' FROM dept AS d, (SELECT COUNT(*) AS _count, deptno FROM emp GROUP BY deptno) AS e WHERE e.deptno = d.deptno; SELECT dname, e.ct FROM dept INNER JOIN (SELECT deptno, COUNT(*) AS ct FROM emp GROUP BY deptno) AS e WHERE dept.deptno = e.deptno; SELECT d.`dname`, COUNT(*) FROM dept AS d RIGHT JOIN emp AS e ON d.`deptno`=e.`deptno` GROUP BY d.`deptno`;
-
查询每种工作的最高工资、最低工资、人数
- 列:部门、最高工资、最低工资、人数(其中最高工资、最低工资、人数,都是分组信息)
- 表:emp
- 条件:无
- 分组:每种工资是分组信息,最高工资使用max(sal),最低工资使用min(sal),人数使用count(*)
1
SELECT job, MAX(sal), MIN(sal), COUNT(1) FROM emp GROUP BY job;
-
显示非销售人员工作名称以及从事同一工作雇员的月工资的总和,并且要满足从事同一工作的雇员的月工资合计大于50000,输出结果按月工资的合计升序排列
- 列:工作名称、工资和(分组信息)
- 表:emp
- 条件:无
- 分组:从事同一工作的工资和,即使用job分组
- 分组条件:工资合计>50000,这是分组条件,而不是where条件
- 排序:工资合计排序,即sum(sal) asc
1 2 3 4 5 6 7 8 9
SELECT job,SUM(sal) FROM emp GROUP BY job HAVING SUM(sal)>50000 ORDER BY SUM(sal) ASC; select job, sum(sal) from emp where job not in('销售员') group by job having sum(sal) > 50000 order by sum(sal) asc; select e.job, _sum as 'sum' from emp join (select sum(sal) as _sum, job from emp group by job) as e on e.job = emp.job where _sum > 50000 and emp.job!='销售员' GROUP BY job order by sal asc;
1.2 子查询
-
查出至少有一个员工的部门。显示部门编号、部门名称、部门位置、部门人数
- 列:部门编号、部门名称、部门位置、部门人数(分组)
- 列:dept、emp(部门人数没有员工表不行)
- 条件:没有
- 分组条件:人数>1
部门编号、部门名称、部门位置在dept表中都有,只有部门人数需要使用emp表,使用deptno来分组得到。 我们让dept和(emp的分组查询),这两张表进行连接查询
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
SELECT z.*,d.dname,d.loc FROM dept d, (SELECT deptno, COUNT(*) cnt FROM emp GROUP BY deptno) z WHERE z.deptno=d.deptno; SELECT d.*, cnt FROM (SELECT *, COUNT(*) AS cnt FROM emp GROUP BY deptno) AS e, dept AS d WHERE d.deptno = e.deptno; SELECT d.*, _count FROM dept AS d INNER JOIN (SELECT deptno, COUNT(*) AS _count FROM emp GROUP BY deptno) AS e ON e.deptno = d.deptno; SELECT d.deptno, d.dname, d.loc, _count FROM dept AS d JOIN (SELECT COUNT(*) AS _count, deptno FROM emp GROUP BY deptno HAVING COUNT(*) > 1) AS e ON e.deptno = d.deptno; SELECT d.deptno, d.dname, d.loc, e.cnt FROM dept AS d INNER JOIN (SELECT deptno, COUNT(*) AS cnt FROM emp GROUP BY deptno HAVING COUNT(deptno) > 1) AS e ON e.deptno = d.deptno; SELECT d.*, COUNT(1) FROM dept AS d RIGHT JOIN emp AS e ON e.`deptno`=d.`deptno` GROUP BY e.`deptno`;
-
列出薪金比关羽高的所有员工
- 列:所有
- 表:emp
- 条件:sal>关羽的sal,其中关羽的sal需要子查询
1 2 3 4 5 6
SELECT * FROM emp e WHERE e.sal > (SELECT sal FROM emp WHERE ename='关羽') SELECT * FROM emp WHERE sal > (SELECT sal FROM emp WHERE ename='关羽');
-
列出所有员工的姓名及其直接上级的姓名
- 列:员工名、领导名
- 表:emp、emp
- 条件:领导.empno=员工.mgr
emp表中存在自身关联,即empno和mgr的关系。 我们需要让emp和emp表连接查询。因为要求是查询所有员工的姓名,所以不能用内连接,因为曾阿牛是BOSS,没有上级,内连接是查询不到它的。
1 2 3 4 5 6
SELECT e.ename, IFNULL(m.ename, 'BOSS') AS 'lead' FROM emp e LEFT JOIN emp m ON e.mgr=m.empno; SELECT e.ename, IFNULL(m.ename, 'BOSS') AS 'lead' FROM emp AS e LEFT JOIN emp AS m ON e.`mgr` = m.`empno`
-
列出受雇日期早于直接上级的所有员工的编号、姓名、部门名称
- 列:编号、姓名、部门名称
- 表:emp、dept
- 条件:hiredate < 领导.hiredate
emp表需要查。部门名称在dept表中,所以也需要查。领导的hiredate需要查,这说明需要两个emp和一个dept连接查询即三个表连接查询
1 2 3 4 5 6 7 8 9 10 11 12
SELECT e.empno, e.ename, d.dname FROM emp e LEFT JOIN emp m ON e.mgr=m.empno LEFT JOIN dept d ON e.deptno=d.deptno WHERE e.hiredate<m.hiredate; --- 错误的 SELECT e1.empno, e1.ename, d.dname FROM emp AS e1 LEFT JOIN emp AS e2 ON e1.mgr = e2.empno AND e1.hiredate < e2.hiredate --on 之后的and条件 无效 LEFT JOIN dept AS d ON e1.deptno = d.deptno;
-
列出部门名称和这些部门的员工信息,同时列出那些没有员工的部门
- 列:员工表所有列、部门名称
- 表:emp, dept
- 要求列出没有员工的部门,这说明需要以部门表为主表使用外连接
1 2 3
SELECT e.*, d.dname FROM emp e RIGHT JOIN dept d ON e.deptno=d.deptno;
-
列出所有文员的姓名及其部门名称,部门的人数
- 列:姓名、部门名称、部门人数
- 表:emp emp dept
- 条件:job=文员
- 分组:emp以deptno得到部门人数
- 连接:emp连接emp分组,再连接dept
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
SELECT e.job, e.ename, d.dname, z.cnt FROM emp e, (SELECT deptno, COUNT(*) cnt FROM emp GROUP BY deptno) z, dept d WHERE e.job = '文员' AND e.deptno=d.deptno AND z.deptno=d.deptno; SELECT e.job, e.ename, d.dname, cnt FROM emp AS e LEFT JOIN dept AS d ON d.deptno = e.deptno LEFT JOIN (SELECT deptno, COUNT(*) AS cnt FROM emp GROUP BY deptno) AS e2 ON e2.deptno = e.deptno WHERE e.job = '文员'; SELECT d.dname, e.ename, c.cnt FROM dept AS d RIGHT JOIN (SELECT deptno, COUNT(deptno) AS cnt FROM emp GROUP BY deptno) AS c ON d.deptno = c.deptno LEFT JOIN (SELECT deptno, ename FROM emp WHERE job='文员') AS e ON d.`deptno` = e.deptno; SELECT e.job, e.ename, _count FROM emp AS e INNER JOIN dept AS d ON d.`deptno`=e.`deptno` RIGHT JOIN (SELECT deptno, COUNT(*) AS _count FROM emp GROUP BY deptno) AS m ON e.`deptno` = m.deptno WHERE job = '文员'
-
列出最低薪金大于15000的各种工作及从事此工作的员工人数
- 列:工作,该工作人数
- 表:emp
- 分组:使用job分组
- 分组条件:min(sal)>15000
1 2 3 4
SELECT job, COUNT(*) FROM emp e GROUP BY job HAVING MIN(sal) > 15000;
-
列出在销售部工作的员工的姓名,假定不知道销售部的部门编号
- 列:姓名
- 表:emp, dept
- 条件:所在部门名称为销售部,这需要通过部门名称查询为部门编号,作为条件
1 2 3
SELECT e.ename FROM emp e WHERE e.deptno = (SELECT deptno FROM dept WHERE dname='销售部');
-
列出薪金高于公司平均薪金的所有员工信息,所在部门名称,上级领导,工资等级
- 列:员工所有信息(员工表),部门名称(部门表),上级领导(员工表),工资等级(等级表)
- 表:emp, dept, emp, salgrade
- 条件:sal>平均工资,子查询
- 所有员工,说明需要左外
1 2 3 4 5 6 7 8 9 10 11 12 13
SELECT e.*, d.dname, m.ename, s.grade FROM emp e NATURAL LEFT JOIN dept d LEFT JOIN emp m ON m.empno=e.mgr LEFT JOIN salgrade s ON e.sal BETWEEN s.losal AND s.hisal WHERE e.sal > (SELECT AVG(sal) FROM emp); select e.*, d.dname, m.ename, s.grade from emp as e left join dept as d on e.deptno = d.deptno left join emp as m on e.mgr = m.empno left join salgrade as s on e.sal between s.losal and s.hisal where e.sal > (select avg(sal) from emp);
注意:聚合函数只会显示一行
-
列出与庞统从事相同工作的所有员工及部门名称
- 列:员工表所有列,部门表名称
- 表:emp, dept
- 条件:job=庞统的工作,需要子查询,与部门表连接得到部门名称
1 2 3
SELECT e.*, d.dname FROM emp e, dept d WHERE e.deptno=d.deptno AND e.job=(SELECT job FROM emp WHERE ename='庞统');
-
列出薪金高于在部门30工作的所有员工的薪金的员工姓名和薪金、部门名称
- 列:姓名、薪金、部门名称(需要连接查询)
- 表:emp, dept
- 条件:sal > all(30部门薪金),需要子查询
1 2 3 4 5 6 7 8
SELECT e.ename, e.sal, d.dname FROM emp e, dept d WHERE e.deptno=d.deptno AND sal > ALL(SELECT sal FROM emp WHERE deptno=30) select e.ename, e.sal, d.dname from emp as e left join dept as d on e.deptno = d.deptno where sal > (select max(sal) from emp where deptno=30);
-
列出在每个部门工作的员工数量、平均工资
- 列:部门名称, 部门员工数,部门平均工资
- 表:emp, dept
- 分组:deptno
1 2 3 4 5 6 7
SELECT d.dname, e.cnt, e.avgsal FROM (SELECT deptno, COUNT(*) cnt, AVG(sal) avgsal FROM emp GROUP BY deptno) e, dept d WHERE e.deptno=d.deptno; SELECT d.dname, COUNT(*), AVG(sal) FROM emp AS e INNER JOIN dept AS d ON d.`deptno`=e.`deptno` GROUP BY e.deptno