mysql学习十一:示例
1.取得每个部门最高薪水的人员名称。一张表。
第一步:求出每个部门的最高薪水,以部门分组
select e.deptno,max(e.sal) as maxsal from emp e group by e.deptno;
第二步:将以上查询结果当成一个临时表t(deptno,maxsal),此临时表作为查询的主表;再与此表e表连接找出人员名称,t.deptno=e.deptno作为连接条件,maxsal=e.sal作为查询条件。
select xxx from t join emp e on e.deptno=t.deptno where t.maxsal=e.sal;
SELECT e.deptno, e.ename, t.maxsal, e.sal FROM ( SELECT e.deptno, max( e.sal ) AS maxsal FROM emp e GROUP BY e.deptno ) t JOIN emp e ON t.deptno = e.deptno WHERE t.maxsal = e.sal ORDER BY e.deptno;
2.哪些人的薪水在部门平均薪水之上
同上题一样,分两步,第一步:求出每个部门的平均薪水
SELECT e.deptno, avg( e.sal ) AS avgsal FROM emp e GROUP BY e.deptno
第二步:将以上查询结果作为临时表t,再与此表连接,此表中的每条数据与临时表中部门的平均薪水作比较。
select xxx from t join emp e on e.deptno=t.deptno where e.sal > t.avgsal;
select t.deptno,e.ename from (select e.deptno,avg(e.sal) as avgsal from emp e group by e.deptno) t join emp e on e.deptno=t.deptno where e.sal > t.avgsal;
3.取得部门中(所有人)的平均薪水等级
3.1取得部门中所有人的平均薪水的等级
第一步:求出部门的平均薪水
select e.deptno,avg(e.sal) as avgsal from emp e group by e.deptno;
第二:以上的平均薪水,对应的等级
将第一步查询结果,作为临时表t ,作为from查询主表
select xxx from t join salgrade s on t.avgsal between s.losal and s.hisal;
select t.deptno,t.avgsal,s.grade from
(select e.deptno,avg(e.sal) as avgsal from emp e group by e.deptno) t join salgrade s on t.avgsal between s.losal and s.hisal;
3.2取得部门中所有人的平均的薪水等级
第一步:求出每个人的薪水等级
select e.deptno,e.name,s.grade from emp e join salgrade s on e.sal between s.losal and s.hisal order by e.deptno;
第二步:求出部门的平均的薪水等级。将以上查询结果,当作临时表t,以部门分组,求出s.grade的平均值
select t.deptno,avg(t.grade) as avgGrade from t group by t.deptno;
select t.deptno,avg(t.grade) as avgGrade from (select e.deptno,e.name,s.grade from emp e join salgrade s on e.sal between s.losal and s.hisal order by e.deptno) t group by t.deptno;
4.不使用组函数max,取得最高薪水,最低薪水
方案一:
select sal from emp order by sal desc limit 1
select sal from emp order by sal asc limit 1
方案二:
select sal from emp where sal not in (select distinct a.sal from emp a join emp b on a.sal < b.sal);
select sal from emp where sal not in (select distinct a.sal from emp a join emp b on a.sal > b.sal);
5.取得平均薪水最高的部门的部门编号
第一步:求出各部门的平均薪水
select e.deptno, avg(e.sal) as avgsal from emp e group by e.deptno;
第二:对以上查询结果,取出最大值
select max(t.avgsal) as maxavgsal from
(select e.deptno, avg(e.sal) as avgsal from emp e group by e.deptno) t;
如果最大值有多个并列,
以上结果求出的最大值,只有一个
以下查询,则列出多个
select e.deptno, avg(e.sal) as avgsal from emp e group by e.deptno having avgsal=(select max(t.avgsal) as maxavgsal from (select e.deptno, avg(e.sal) as avgsal from emp e group by e.deptno) t);
6.求出平均薪水最高的部门的部门名称
select e.deptno,d.dname, avg(e.sal) as avgsal from emp e join dept d on e.deptno=d.deptno group by e.deptno,d.dname having avgsal=select max(t.avgsal) as maxavgsal from (select e.deptno, avg(e.sal) as avgsal from emp e group by e.deptno t);
或者将5题的结果作为临时表,再从dept表中查找部门名称,也可以。
7.求平均薪水的等级最低的部门的部门名称
第一步:部门的平均薪水
select e.deptno,d.dname,avg(e.sal) as avgsal
from emp e join dept d on e.deptno=d.deptno group by e.deptno,d.dname;
第二步:将以上查询结果,作为临时 表t,与salgrade表进行连接:t.avgsal between s.losal and s.hisal
select t.dept,t.dname,s.grade
from t join salgrade s on t.avgsal between s.losal and s.hisal;
第三步:将以上查询结果,作为临时表t
select min(t.grade) as minGrade from t;
第四步:having或where。
最终结果:
select t.deptno,t.dname,s.grade from (select e.deptno,e.dname,avg(e.sal) as avgsal from emp e join dept d on e.deptno=d.deptno group by e.deptno,d.dname) t join salgrade s on t.avgsal between s.losal and s.hisal where s.grade=( select min(t.grade) as minGrade from ( select t.deptno,t.dname,s.grade from ( select e.deptno,d.dname,avg(e.sal) as avgsal from emp e join dept d on e.deptno=d.deptno group by e.deptno,d.dname) t join salgrade s on t.avgsal between s.losal and s.hisal) t);
8.取得比普通员工最高薪水还要高的经理人姓名
第一步,找出普通员工的最高薪水
1.1找出经理
select distinct mgr from emp;
1.2找出普通员工
in会自动忽略空值;not in 不会自动忽略空值。
如果有null值参与运算,就会出算。因此,在not in时要手动去掉空值。
select * from emp where empno not in (select distinct mgr from emp where mgr is not null);
1.3找出普通员工的最高薪水
select max(sal) as maxsal from emp where empno not in (select distinct mgr from emp where mgr is not null);
2.找出薪水比普通员的最高薪水还要高的经理人姓名
select e.ename from emp e where e.sal >
(select max(sal) as maxsal from emp where empno not in
(select distinct mgr from emp where mgr is not null));
9.取得薪水最高的前五名员工
select * from emp order by sal desc limit 0,5;
mysql默认的排序是升序asc
10.取得薪水最高的第六到第十名员工
select * from emp order by sal desc limit 5, 5;
mysql的下标,是从0开始的。
11.取得最近入职的5名员工
select * from emp order by hiredate desc limit 0, 5;
排序除了可以通过数值,还可以通过日期date来排序
12.取得每个薪水等级有多少员工
1.取得每个员工的薪水等级
SELECT e.ename, s.grade FROM emp e JOIN salgrade s ON e.sal BETWEEN s.losal AND s.hisal ORDER BY s.grade;
2.
select t.grade,count(t.ename) from (SELECT e.ename, s.grade FROM emp e JOIN salgrade s ON e.sal BETWEEN s.losal AND s.hisal ) t group by t.grade;
13.有3个表s学生表,c课程表,sc学生选课表
s(sno, sname)学号,姓名
c(cno,cname,cteacher)课号,课名,老师
sc(scno, cno, scgrade)学号,课号,成绩
问题:
1.找出没有选过“黎明”老师的所有学生的姓名
2.列出2门以上(含2门)不及格学生姓名及平均成绩。
3.既学过1号课程又学过2号课程的所有学生的姓名
CREATE TABLE s ( sno INT ( 4 ) PRIMARY KEY auto_increment, sname VARCHAR ( 32 ) );
CREATE TABLE c( cno INT ( 4 ) PRIMARY KEY auto_increment, cname VARCHAR ( 32 ), cteacher varchar(32) );
学生与课程表之间,是多对多的关系;因此成绩表的主键,设置为学生与课程表id联合主键;
同时成绩表的sno和学生表是外键的关系,成绩表的cno和课程表是外键关系。
CREATE TABLE sc( sno INT ( 4 ), cno INT ( 4 ), 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) );
修改为中文字符集
ALTER TABLE `mydb`.`s` CHARACTER SET = utf8, COLLATE = utf8_general_ci;
ALTER TABLE `mydb`.`s` MODIFY COLUMN `sname` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL AFTER `sno`;
insert into s(sname) values('张三'), ('李四'), ('王五'), ('赵六');
ALTER TABLE `mydb`.`c` MODIFY COLUMN `cname` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL AFTER `cno`, MODIFY COLUMN `cteacher` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL AFTER `cname`, CHARACTER SET = utf8, COLLATE = utf8_general_ci;
insert into c(cname,cteacher) values('java','吴老师'), ('c','王老师'), ('python','张老师'), ('mysql', '黎明');
insert into sc(sno,cno, scgrade) values(1,1,30), (1,2,50),(1,3,80),(1,4,90),(1,5,70),(2,2,80),(2,3,50),(2,4,70),(2,5,80),(3,1,60),(3,2,70),(3,3,80),(4,3,50);
1.1找出黎明老师的授课编号
select cno from c where cteacher='黎明';
1.2找出选过黎明老师的学生编号
select sno from sc where cno=(select cno from c where cteacher='黎明');
1.3没有选过的黎明老师的学生
select * from s where sno not in
(select sno from sc where cno=(select cno from c where cteacher='黎明'))
2.1找出2门不及学生的编号
SELECT sc.sno, count( * ) AS studentNum FROM sc WHERE scgrade < 60 GROUP BY sc.sno HAVING studentNum >= 2;
2.2找出其姓名
SELECT sc.sno, s.sname, count( * ) AS studentNum FROM sc JOIN s ON sc.sno = s.sno WHERE scgrade < 60 GROUP BY sc.sno, s.sname HAVING studentNum >= 2;
此表作为临时表t1
2.3学生的平均成绩
select sc.sno, avg(sc.scgrade) as scgrade from sc group by sc.sno;
此表作为临时表t2
2.4 2门以上(含2门)不及格学生姓名及平均成绩
select t1.sname,t2.avgscgrade from t1 join t2 on t1.sno=t2.sno;
或者
SELECT sc.sno, s.sname, count( * ) AS studentNum, avg(sc.scgrade) as avggrade FROM sc JOIN s ON sc.sno = s.sno WHERE scgrade < 60 GROUP BY sc.sno, s.sname HAVING studentNum >= 2;
3.1
SELECT sc.sno,s.sname FROM sc JOIN s ON sc.sno=s.sno WHERE cno = 1 AND sc.sno IN ( SELECT sno FROM sc WHERE cno = 2 );
14.列出所有员工及领导的名字
有些员工,没有mgr,因此必须用外连接
select e.ename, b.ename as leadername from emp e left join emp b on e.mgr=b.empno;
15.列出受雇日期早于其直接上级的所有员工编号、姓名、部门名称
select e.empno,e.ename,d.deptno,d.dname from emp e join emp b on e.mgr=b.empno join dept d on e.deptno=d.deptno where e.hiredate < b.hiredate;
16.列出部门名称和这些部门的员工信息,同时列出哪些没有员工的部门
select d.dname,e.* from emp e right join dept d on e.deptno=d.deptno
17.列出至少有5个员工的所有部门
1.1求出每个部门的员工数量
select e.deptno, count(e.ename) as total from emp e group by e.deptno;
1.2
select e.deptno, count(e.ename) as total from emp e group by e.deptno having total >= 5;
18.列出薪水比bob高的所有员工信息
1.1 bob的薪水
select sal from emp where ename='bob'
1.2
select sal from emp where sal > (select sal from emp where ename='bob');
19.列出所有clerk职位的姓名及其部门名称,部门人数
1.1clerk职位的姓名及其部门名称
select e.ename,e.deptno,d.dname from emp e join dept d on e.deptno=d.deptno where e.job='clerk';
此表作为t1
1.2部门人数
select e.deptno,count(e.ename) as totalEmp from emp e group by e.deptno;
此表作为t2
select xxx
from t1
join t2
on t1.deptno=t2.deptno
select t1.deptno,t1.dname,t1.ename,t2.totalEmp from (select e.ename,e.deptno,d.dname 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
20.列出最低薪水大于3000的各种工作及从事此工作的全部雇员人数
第一步:求出每种工作岗位的最低薪水
select e.job, min(e.sal) as minsal from emp e group by e.job;
第二步:having
select e.job, min(e.sal) as minsal from emp e group by e.job having minsal > 3000;
第三步:此工作岗位的总人数
select e.job, min(e.sal) as minsal, count(e.ename) as totalEmp from emp e group by e.job having minsal > 3000;
21.列出在部门finance工作的员工的姓名,假定不知道finance部门的部门编号
select deptno from dept where dname='finance'
select ename from emp where deptno = (select deptno from dept where dname='finance');
22.列出薪金高于公司平均薪金的所有员工,所在部门、上级领导、雇员的工资等级
第一步:求出公司的平均薪水
select avg(sal) avgsal from emp;
第二步:
select xxx
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 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) avgsal from emp);
23.列出与didy从事相同工作的所有员工及部门名称
didy从事相的工作
select job from emp where ename='didy';
及其部门名称
SELECT d.dname, e.* FROM emp e JOIN dept d ON e.deptno = d.deptno WHERE e.job = ( SELECT job FROM emp WHERE ename = 'didy' );
24.列出薪金等于部门3中员工的薪金的其它员工的姓名和薪金
部门3中员工的薪金
select distinct sal from emp where deptno=3;
select ename,sal from emp where sal in (select distinct sal from emp where deptno=3) and deptno<>3;
25.列出薪金高于在部门3工作的所有员工的薪金的员工姓名和薪金、部门名称
部门3中的最高薪水
select max(sal) as maxsal from emp where deptno=3;
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=3) ;
26.列出在每个部门工作的员工数量 、平均工资、平均服务期限
select e.deptno, count(e.ename) as totalEmp,avg(e.sal) as avgsal,
avg((TO_DAYS(now()) - TO_DAYS(hiredate))/365) as avgserveryear
from emp e group by e.deptno
27.列出所有员工的姓名、部门名称和工资
select d.dname,e.ename,e.sal from emp e right join dept d on e.deptno=d.deptno
28.列出所有部门的详细信息和人数
select e.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;
29.列出各种工作的最低工资及从事此工作的雇员姓名
select e.job,min(e.sal) as minsal from emp e group by e.job;
将以上查询结果作为临时 表t
select xx
from emp e
join t on e.job=t.job
where e.sal=t.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;
30.列出各个部门manager的最低薪金
select e.deptno,min(e.sal) as minsal from emp e where e.job='manager' group by e.deptno;
31.列出所有员工的年工资,按年薪从低到高排序
select ename,(sal+ifnull(comm, 0))*12 as yearsal from emp order by yearsal asc;
32.求出员工领导的薪水超过3000的员工名称和领导名称
select e.ename,b.ename as leadername from emp e join emp b on e.mgr=b.empno where b.sal > 3000;
33.求出部门中名称带f字符的部门员工的工资合计、部门人数
select d.dname,sum(e.sal) as sumsal,count(e.ename) as totalEmp from emp e join dept d on e.deptno=d.deptno where d.dname like '%f%' group by d.dname;
34.给任职日期超过5年的员工加薪10%
备份表:
create table emp_bask as select * from emp;
update emp_bak set sal=sal*1.1 where (TO_DAYS(now()) - TO_DAYS(hiredate))/365 > 5;
posted on 2018-09-16 23:58 myworldworld 阅读(351) 评论(0) 收藏 举报