34道经典SQL试题(完结附create原数据)

文章目录

MySQL练习题

数据表代码

drop table if exists dept;
drop table if exists salgrade;
drop table if exists emp;
 
create table dept(
		deptno int(10) primary key,
		dname varchar(14),
		loc varchar(13)
		);
		
create table salgrade(
		grade int(11),
		losal int(11),
		hisal int(11)
		);
		
create table emp(
		empno int(4) primary key,
		ename varchar(10),
		job varchar(9),
		mgr int(4),
		hiredate date,
		sal double(7,2),
		comm double(7,2),
		deptno int(2)
		);
		
insert into dept(deptno,dname,loc) values(10,'ACCOUNTING','NEW YORK');
insert into dept(deptno,dname,loc) values(20,'RESEARCHING','DALLAS');
insert into dept(deptno,dname,loc) values(30,'SALES','CHICAGO');
insert into dept(deptno,dname,loc) values(40,'OPERATIONS','BOSTON');
 
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,5000);
 
insert into emp(empno,ename,job,mgr,hiredate,sal,comm,deptno)
	values(7369,'SIMITH','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,null,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);
	
select * from dept;
select * from salgrade;
select * from emp;
drop table if exists s;
drop table if exists c;
drop table if exists sc;
 
create table s(
		sno int(10) primary key,
		sname varchar(14)
		);
		
create table c(
		cno int(10) primary key,
		cname varchar(14),
		cteacher varchar(14)
		);
		
create table sc(
		sno int(10),
  	    cno int(10),
		scgrade int(10),
		primary key(sno,cno)
		);
		
insert into s(sno,sname) values(1,'a');
insert into s(sno,sname) values(2,'b');
insert into s(sno,sname) values(3,'c');
insert into s(sno,sname) values(4,'d');
 
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','黎明');
 
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);
	
select * from s;
select * from c;
select * from sc;

第一题:取得每个部门最高薪水的人员名称

1、首先知道每个部门的最高薪水,通过对每个部门分组,找到最大值
分组查询在显示的字段只有两种,第一分组的字段,就是group by 后面的字段;第二分组函数(比如max)

select e.deptno, max(e.sal) as maxsal 
from emp e group by e.deptno;

在这里插入图片描述
2、查询在10部门中拿5000的是谁,将上表作为临时表t与原表进行连接,连接条件是部门编号相等

select e.deptno, e.ename, e.sal
from t join emp e on t.deptno = e.deptno 
where t.maxsal = e.sal order by e.deptno;

将t表放进去即可

select e.deptno, e.ename, 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;

第二题:哪些人的薪水在部门平均薪水之上

1、求出每个部门的平均薪水

select e.deptno,avg(e.sal) as avgsal 
from emp e group by e.deptno;

在这里插入图片描述
2、将以上查询结果当成临时表t

select e.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.1 取得部门中所有人的平均薪水的 等级(between and)

1、求得每个部门的平均薪水

select e.deptno, avg(e.sal) as avgsal from emp e group by e.deptno;

2、将上表作为临时表t,与等级表做连接

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 取得部门中所有人的平均的 薪水等级

1、求出每个人的薪水等级

select e.deptno, e.ename, s.grade 
from emp e join salgrade s 
on e.sal between s.losal and s.hisal order by e.deptno;

±-------±-------±------+
| deptno | ename | grade |
±-------±-------±------+
| 10 | MILLER | 2 |
| 10 | KING | 5 |
| 10 | CLARK | 4 |
| 20 | FORD | 4 |
| 20 | SCOTT | 4 |
| 20 | JONES | 4 |
| 20 | ADAMS | 1 |
| 20 | SIMITH | 1 |
| 30 | ALLEN | 3 |
| 30 | WARD | 2 |
| 30 | TURNER | 3 |
| 30 | MARTIN | 2 |
| 30 | BLAKE | 4 |
| 30 | JAMES | 1 |
±-------±-------±------+
2、求部门薪水等级的平均值

select t.deptno,avg(t.grade) as avgGrade from 
(select e.deptno, e.ename, 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;

±-------±---------+
| deptno | avgGrade |
±-------±---------+
| 10 | 3.6667 |
| 20 | 2.8000 |
| 30 | 2.5000 |
±-------±---------+

第四题:不准用组函数(max),取得最高薪水(给出两种解决方案)

  • 方法一
select sal from emp limit 0,1 order by sal desc;  -- 错误,应该先排序
select sal from emp order by sal desc limit 0,1;
  • 方法二
    1、自连接,找到a表中所有比b表中小的数
select distinct a.sal from emp a join emp b on a.sal < b.sal;

±--------+
| sal |
±--------+
| 800.00 |
| 1250.00 |
| 1500.00 |
| 1100.00 |
| 950.00 |
| 1300.00 |
| 1600.00
| 2850.00 |
| 2450.00 |
| 2975.00 |
| 3000.00 |
±--------+
2、a表中的数不在临时表t

select e.sal from emp e 
where e.sal not in 
(select distinct a.sal 
from emp a join emp b on a.sal < b.sal);

只要把>变为<就成为了最小值

第五题:取得平均薪水最高的部门的部门编号(可能有一样的最后高薪水部门存在)

1、求部门的平均薪水

select e.deptno,avg(e.sal) as avgsal from emp e group by e.deptno;

±-------±------------+
| deptno | avgsal |
±-------±------------+
| 10 | 2916.666667 |
| 20 | 2175.000000 |
| 30 | 1566.666667 |
±-------±------------+
2、将上表当成临时表t,求得最高薪水

select max(t.avgsal) 
from (select e.deptno,avg(e.sal) as avgsal 
from emp e group by e.deptno) as t;

3、求得最高的薪水部门编号

select e.deptno,avg(e.sal) as avgsal 
from emp e group by e.deptno 
having 
avgsal = (select max(t.avgsal) 
from (select e.deptno,avg(e.sal) as avgsal 
from emp e group by e.deptno) as t);

第六题:取得平均薪水最高的部门的部门名称

1、求每个部门平均薪水

select e.deptno, avg(e.sal) as avgsal 
from emp e group by e.deptno;

2、求最高的平均薪水

select max(t.avgsal) 
from (select e.deptno, avg(e.sal) as avgsal 
from emp e group by e.deptno) as t;

3、部门名称在另外一个表中,所以需要连接

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) 
from (select e.deptno, avg(e.sal) as avgsal 
from emp e group by e.deptno) as t);

第七题:求平均薪水的等级最低的部门的部门名称

1、部门的平均薪水+部门名称

select e.deptno, d.dname, avg(e.sal) as avgsal from emp e 
join dept d on d.deptno = e.deptno group by e.deptno, d.dname;

±-------±------------±------------+
| deptno | dname | avgsal |
±-------±------------±------------+
| 10 | ACCOUNTING | 2916.666667 |
| 20 | RESEARCHING | 2175.000000 |
| 30 | SALES | 1566.666667 |
±-------±------------±------------+
2、求等级,将以上查询结果当成临时表t与等级表连接

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 d.deptno = e.deptno group by e.deptno, d.dname) t 
join salgrade s on t.avgsal between s.losal and s.hisal;

±-------±------------±------+
| deptno | dname | grade |
±-------±------------±------+
| 10 | ACCOUNTING | 4 |
| 20 | RESEARCHING | 4 |
| 30 | SALES | 3 |
±-------±------------±------+
3、最低的等级

select min(h.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 d.deptno = e.deptno group by e.deptno, d.dname) t 
join salgrade s on t.avgsal between s.losal and s.hisal) h;

±---------+
| mingrade |
±---------+
| 3 |
±---------+
4、过滤(这里的过滤使用where)
having 必须用在group by之后,where用在group by 之前,having是对分组之后的数据仍然不满意的情况下进行过滤

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 d.deptno = e.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(h.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 d.deptno = e.deptno group by e.deptno, d.dname) t 
join salgrade s on t.avgsal between s.losal and s.hisal) h);

第八题:取得比普通员工(员工代码没有在mgr上出现的)的最高薪水还要高的经理人姓名

1、先找到普通员工(员工代码没有在mgr上出现的)
1.1 先找到mgr有哪些人

select distinct mgr from emp;

±-----+
| mgr |
±-----+
| 7902 |
| 7698 |
| 7839 |
| 7566 |
| NULL |
| 7788 |
| 7782 |
±-----+

select * from emp where empno not in (select distinct mgr from emp);

但是我们却查询为空(实际上是有的)
原因是in后面的语句中有NULL,而not in 不会自动忽略空值,in会自动忽略空值,not in 里面的参数值的关系值都是and,in里面的参数值的关系都是or
什么意思呢?如果not in 不忽略NULL,则会导致NULL参与了数学运算。有NULL参与的数学运算结果都为NUll
记住这句话就好了not in 的结果集 中不能出现null,否则查询结果为空,我们必须用where语句将NULL删除

select * from emp 
where empno not in 
(select distinct mgr from emp where mgr is not NULL );

±------±-------±---------±-----±-----------±--------±--------±-------+
| empno | ename | job | mgr | hiredate | sal | comm | deptno |
±------±-------±---------±-----±-----------±--------±--------±-------+
| 7369 | SIMITH | CLERK | 7902 | 1980-12-17 | 800.00 | NULL | 20 |
| 7499 | ALLEN | SALESMAN | 7698 | 1981-02-20 | 1600.00 | 300.00 | 30 |
| 7521 | WARD | SALESMAN | 7698 | 1981-02-22 | 1250.00 | 500.00 | 30 |
| 7654 | MARTIN | SALESMAN | 7698 | 1981-09-28 | 1250.00 | 1400.00 | 30 |
| 7844 | TURNER | SALESMAN | 7698 | 1981-09-08 | 1500.00 | NULL | 30 |
| 7876 | ADAMS | CLERK | 7788 | 1987-05-23 | 1100.00 | NULL | 20 |
| 7900 | JAMES | CLERK | 7698 | 1981-12-03 | 950.00 | NULL | 30 |
| 7934 | MILLER | CLERK | 7782 | 1982-01-23 | 1300.00 | NULL | 10 |
±------±-------±---------±-----±-----------±--------±--------±-------+
1.2 找到最高薪水

select max(sal) as maxsal 
from emp where empno not in 
(select distinct mgr from emp where mgr is not NULL );

±--------+
| maxsal |
±--------+
| 1600.00 |
±--------+
2 找到比最高薪水还要高的经理(直接大于最高薪水就好了,因为大于最高薪水的已经没有普通人了)

select ename from emp 
where sal > 
(select max(sal) as maxsal from emp 
where empno not in 
(select distinct mgr from emp where mgr is not NULL ));

第九题:取得薪水最高的前五名员工

select e.ename from emp e order by e.sal desc limit 0,5;

第十题:取得薪水最高的第六到第十名员工

select e.ename from emp e order by e.sal desc limit 5,5;

第十一题:取得最后入职的5名员工

select e.ename from emp e order by e.hiredate desc limit 0,5;

第十二题:取得每个薪水等级有多少员工

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、以上查询结果为临时表t,等级分组,count

select t.grade, count(*) as total 
from 
(select e.ename, s.grade 
from emp e join salgrade s 
on e.sal between s.losal and s.hisal 
order by s.grade) t 
group by t.grade; 

第十三题

有三个表s(学生表),c(课程表),sc(学生选课表)
S(SNo, SName)代表(学号, 姓名)
C(CNo, CName, CTeacher)代表(课号, 课名, 老师)
SC(SNo, CNo, Score)代表(学号, 课号, 成绩)

问题:
1、找出没选过‘黎明老师’的所有学生名单
2、列出2门以上(含2门)不及格学生姓名以及学生成绩
3、既学过1号课程又学过2号课程所有学生的姓名

创建表时每张表都要有主键

drop table if exists s;
drop table if exists c;
drop table if exists sc;
 
create table s(
		sno int(10) primary key auto_increment,
		sname varchar(32)
		);
		
create table c(
		cno int(10) primary key auto_increment,
		cname varchar(32),
		cteacher varchar(32)
		);
# sc表中学生与课程是多对多关系,主键设成谁(复合主键(sno,cno))	
# sno和cno也必须来自学生表和课程表,因此他们是主键的同时也是外键
# 一个表只能有一个主键但是可以有多个外键
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(sname) values('张三');
insert into s(sname) values('李四');
insert into s(sname) values('王五');
insert into s(sname) values('赵六');
 
insert into c(cname,cteacher) values('java','王老师');
insert into c(cname,cteacher) values('C++','张老师');
insert into c(cname,cteacher) values('C#','李老师');
insert into c(cname,cteacher) values('mysql','周老师');
insert into c(cname,cteacher) values('oracle','黎明');
 
insert into sc(sno,cno,scgrade) values(1,1,30);
insert into sc(sno,cno,scgrade) values(1,2,50);
insert into sc(sno,cno,scgrade) values(1,3,80);
insert into sc(sno,cno,scgrade) values(1,4,80);
insert into sc(sno,cno,scgrade) values(1,5,70);
insert into sc(sno,cno,scgrade) values(2,2,80);
insert into sc(sno,cno,scgrade) values(2,3,50);
insert into sc(sno,cno,scgrade) values(2,4,70);
insert into sc(sno,cno,scgrade) values(2,5,80);
insert into sc(sno,cno,scgrade) values(3,1,60);
insert into sc(sno,cno,scgrade) values(3,2,70);
insert into sc(sno,cno,scgrade) values(3,3,60);
insert into sc(sno,cno,scgrade) values(4,3,50);
insert into sc(sno,cno,scgrade) values(4,5,40);
	
select * from s;
select * from c;
select * from sc;

1、找出没选过”黎明”老师的所有学生姓名

1.1、找出选过”黎明”老师的学生学号 --》黎明老师教的啥课

select cno from c where cteacher = '黎明'
select sno from sc where cno = (select cno from c where cteacher = '黎明');

1.2、找出没选过”黎明”老师的学生姓名

select * from s 
where s.sno not in 
(select sno from sc where cno = (select cno from c where cteacher = '黎明'));

2、列出2门以上(含2门)不及格学生姓名及平均分

2.1 先找到不及格的学生(group by 放在分组前,分组之前能把学生过滤点就过滤点)

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;

2.3 还有平均得分

select sc.sno, avg(sc.scgrade) avggrade from sc group by sc.sno;

2.4 3表与2表连接

select t1.sname, t2.avggrade 
from (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 
join (select sc.sno, avg(sc.scgrade) avggrade from sc group by sc.sno) t2 
on t1.sno = t2.sno;

3、既学过1号课程也学过2号课程的学生 (高频)

select sno from sc where cno = 1;
select sno from sc where cno = 2;

思路:学过1号课程的人cno = 1and这些学生的编号又在表2

select sno from sc where cno = 1 
and sc.sno in 
(select sno from sc where cno = 2);

找到姓名

select 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);

第十四题:列出所有员工及领导的名字(重点“所有”)

自连接

select a.ename, b.ename as leadername from emp a join emp b 
on a.mgr = b.empno;

±-------±-----------+
| ename | leadername |
±-------±-----------+
| SIMITH | FORD |
| ALLEN | BLAKE |
| WARD | BLAKE |
| JONES | KING |
| MARTIN | BLAKE |
| BLAKE | KING |
| CLARK | KING |
| SCOTT | JONES |
| TURNER | BLAKE |
| ADAMS | SCOTT |
| JAMES | BLAKE |
| FORD | JONES |
| MILLER | CLARK |
±-------±-----------+
这个是有问题的,King没有,题目上是找到所有的员工,所以应该是外连接

select a.ename, b.ename as leadername from emp a left join emp b 
on a.mgr = b.empno;

±-------±-----------+
| ename | leadername |
±-------±-----------+
| SIMITH | 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 |
±-------±-----------+

第十五题:列出受雇日期早于其直接上级的所有员工编号、姓名、部门名称(三表连接)

1、先找到早于上级的员工编号、姓名(自连接)

select a.empno, a.ename from emp a join emp b 
on a.mgr = b.empno 
where a.hiredate < b.hiredate

±------±-------+
| empno | ename |
±------±-------+
| 7369 | SIMITH |
| 7499 | ALLEN |
| 7521 | WARD |
| 7566 | JONES |
| 7698 | BLAKE |
| 7782 | CLARK |
±------±-------+

2、连接部门表

select a.empno, a.ename, d.dname from emp a join emp b 
on a.mgr = b.empno join dept d on a.deptno = d.deptno 
where a.hiredate < b.hiredate;

±------±-------±------------+
| empno | ename | dname |
±------±-------±------------+
| 7369 | SIMITH | RESEARCHING |
| 7499 | ALLEN | SALES |
| 7521 | WARD | SALES |
| 7566 | JONES | RESEARCHING |
| 7698 | BLAKE | SALES |
| 7782 | CLARK | ACCOUNTING |
±------±-------±------------+

第十六题:列出部门名称和这些部门的员工信息,同时列出那些没有员工的部门(外连接)

select d.dname, e.* from emp e right join dept d 
on e.deptno = d.deptno order by d.dname;

第十七题:列出至少有5个员工的所有部门

1、先求每个部门的员工数量

select e.deptno,count(e.ename) as totalname from emp e 
group by e.deptno;

2、现在我对分组之后的数据不满意了,使用having进行过滤

select e.deptno,count(e.ename) as totalname from emp e 
group by e.deptno having totalname >= 5;

±-------±----------+
| deptno | totalname |
±-------±----------+
| 20 | 5 |
| 30 | 6 |
±-------±----------+

第十八题:列出薪水比"SIMITH"多的所有员工信息

select sal from emp where ename = 'SIMITH';
select * from emp where sal > (select sal from emp where ename = 'SIMITH');

第十九题:列出所有"CLERK"(办事员)的姓名及其部门名称,部门人数

select d.dname, d.deptno, e.ename from emp e join dept d on e.deptno = d.deptno 
where e.job = 'CLERK';
  • 求出每个部门的员工数量
select e.deptno,count(e.ename) as totalname from emp e group by 
e.deptno;
  • 两张表连接
select t1.deptno,t1.dname, t1.ename, t2.totalname from 
(select d.dname, d.deptno, 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 totalname from emp e group by 
e.deptno) t2 
on t1.deptno = t2.deptno;

第二十题:列出最低薪水大于1500的各种工作以及从事此工作的全部雇员人数

select e.job, min(e.sal) as minsal 
from emp e 
group by e.job having minsal > 1500;

±----------±--------+
| job | minsal |
±----------±--------+
| ANALYST | 3000.00 |
| MANAGER | 2450.00 |
| PRESIDENT | 5000.00 |
±----------±--------+

  • 从事此工作的雇员人数
select e.job, count(e.ename) as total from emp e 
join (select e.job, min(e.sal) as minsal 
from emp e 
group by e.job having minsal > 1500) t 
on e.job = t.job group by e.job;

±----------±------+
| job | total |
±----------±------+
| ANALYST | 2 |
| MANAGER | 3 |
| PRESIDENT | 1 |
±----------±------+

  • 其实不用那么麻烦,第一个步骤你已经分好组了,直接count就好
select e.job, min(e.sal) as minsal, count(e.ename) as total 
from emp e 
group by e.job having minsal > 1500;

±----------±--------±------+
| job | minsal | total |
±----------±--------±------+
| ANALYST | 3000.00 | 2 |
| MANAGER | 2450.00 | 3 |
| PRESIDENT | 5000.00 | 1 |
±----------±--------±------+

第二十一题:列出在部门"SALES"(销售部)工作的员工姓名,假定不知道销售部门的部门编号

1、不知道部门编号你先求出部门编号

select deptno from dept where dname = 'SALES';

2、开始吧(注意where 后的=只能是一个值,两个值就不能用了)

select e.ename from emp e 
where e.deptno = 
(select deptno from dept where dname = 'SALES');

±-------+
| ename |
±-------+
| ALLEN |
| WARD |
| MARTIN |
| BLAKE |
| TURNER |
| JAMES |
±-------+

第二十二题:列出薪资高于公司平均薪金的所有员工,所在部门,上级领导,雇员的工资等级(四表连接)

1、先求出公司的平均薪水

select avg(sal) as avgsal from emp;

±------------+
| avgsal |
±------------+
| 2073.214286 |

select d.dname, e.ename, e.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 |
±------------±------±-----------±------+
| RESEARCHING | JONES | JONES | 4 |
| SALES | BLAKE | BLAKE | 4 |
| ACCOUNTING | CLARK | CLARK | 4 |
| RESEARCHING | SCOTT | SCOTT | 4 |
| ACCOUNTING | KING | KING | 5 |
| RESEARCHING | FORD | FORD | 4 |
±------------±------±-----------±------+

第二十三题:列出与"SCOTT"从事相同工作的所有员工及部门名称

1、scott的工作是啥

select job from emp where ename = 'scott';

±--------+
| job |
±--------+
| ANALYST |
±--------+
2、

select e.ename, d.dname from emp e 
join dept d on e.deptno = d.deptno 
where e.job = 
(select job from emp where ename = 'scott');

第二十四题:列出薪资等于部门30中员工的薪资的其他部门员工的姓名和薪资

select distinct sal from emp e where e.deptno = 30;

±--------+
| sal |
±--------+
| 1600.00 |
| 1250.00 |
| 2850.00 |
| 1500.00 |
| 950.00 |
±--------+

select e.ename,e.sal from emp e where e.sal 
in (select distinct sal from emp e where e.deptno = 30) 
and e.deptno != 30;

第二十五题:列出薪资高于在部门30工作的所有员工的薪资的员工姓名、薪资和部门名称

select max(sal) as maxsal from emp e where e.deptno = 30;

±--------+
| maxsal |
±--------+
| 2850.00 |
±--------+

select e.ename,e.sal, d.dname from emp e 
join dept d 
on e.deptno = d.deptno 
where e.sal > (select max(sal) as maxsal from emp e where e.deptno = 30);

±------±--------±------------+
| ename | sal | dname |
±------±--------±------------+
| JONES | 2975.00 | RESEARCHING |
| SCOTT | 3000.00 | RESEARCHING |
| KING | 5000.00 | ACCOUNTING |
| FORD | 3000.00 | RESEARCHING |
±------±--------±------------+

第二十六题:列出在每个部门工作的员工数量,平均薪资和平均服务期限(to_days)(now())

  • 我从入职到今天服务时间之和再平均
    函数to_days(日期类型)–>返回天数,
    获取数据库的系统当前时间的函数now();
select to_days(now()); # 从公元零年开始

±---------------+
| to_days(now()) |
±---------------+
| 737879 |
±---------------+
所以服务了多少年:(to_days(now())-to_days(hiredate))/365

select deptno, count(ename) as total, 
avg(sal) as avgsal, 
avg((to_days(now())-to_days(hiredate))/365) as avgdate 
from emp group by deptno;

±-------±------±------------±------------+
| deptno | total | avgsal | avgdate |
±-------±------±------------±------------+
| 10 | 3 | 2916.666667 | 38.47763333 |
| 20 | 5 | 2175.000000 | 36.50466000 |
| 30 | 6 | 1566.666667 | 38.77625000 |
±-------±------±------------±------------+

第二十七题:列出所有员工的姓名、部门名称和工资

select e.ename, d.dname, e.sal 
from 
emp e right join 
dept d 
on e.deptno = d.deptno ;

±-------±------------±--------+
| ename | dname | sal |
±-------±------------±--------+
| SIMITH | RESEARCHING | 800.00 |
| ALLEN | SALES | 1600.00 |
| WARD | SALES | 1250.00 |
| JONES | RESEARCHING | 2975.00 |
| MARTIN | SALES | 1250.00 |
| BLAKE | SALES | 2850.00 |
| CLARK | ACCOUNTING | 2450.00 |
| SCOTT | RESEARCHING | 3000.00 |
| KING | ACCOUNTING | 5000.00 |
| TURNER | SALES | 1500.00 |
| ADAMS | RESEARCHING | 1100.00 |
| JAMES | SALES | 950.00 |
| FORD | RESEARCHING | 3000.00 |
| MILLER | ACCOUNTING | 1300.00 |
| NULL | OPERATIONS | NULL |
±-------±------------±--------+

第二十八题:列出所有部门的详细信息和人数

select d.deptno, d.dname, d.loc, count(e.ename) as total from emp e 
right join dept d on e.deptno = d.deptno 
group by d.deptno, d.dname, d.loc;

±-------±------------±---------±------+
| deptno | dname | loc | total |
±-------±------------±---------±------+
| 10 | ACCOUNTING | NEW YORK | 3 |
| 20 | RESEARCHING | DALLAS | 5 |
| 30 | SALES | CHICAGO | 6 |
| 40 | OPERATIONS | BOSTON | 0 |
±-------±------------±---------±------+

第二十九题:列出各种工作的最低工资以及从事此工作的雇员姓名

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

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 |
±-------+
| SIMITH |
| WARD |
| MARTIN |
| CLARK |
| SCOTT |
| KING |
| FORD |
±-------+

第三十题:列出各个部门manager的最低薪资

select e.deptno, min(e.sal) as minsal from emp e 
where e.job = 'MANAGER' 
group by e.deptno;

±-------±--------+
| deptno | minsal |
±-------±--------+
| 10 | 2450.00 |
| 20 | 2975.00 |
| 30 | 2850.00 |
±-------±--------+

第三十一题:列出所有员工的年工资,按年薪从低到高排序(ifnull)

IFNULL() 函数用于判断第一个表达式是否为 NULL,如果为 NULL 则返回第二个参数的值,如果不为 NULL 则返回第一个参数的值。
工资 = sal + comm

select e.ename, (e.sal+ifnull(comm, 0))*12  as yearsal from emp e 
order by yearsal asc;

±-------±---------+
| ename | yearsal |
±-------±---------+
| SIMITH | 9600.00 |
| JAMES | 11400.00 |
| ADAMS | 13200.00 |
| MILLER | 15600.00 |
| TURNER | 18000.00 |
| WARD | 21000.00 |
| ALLEN | 22800.00 |
| CLARK | 29400.00 |
| MARTIN | 31800.00 |
| BLAKE | 34200.00 |
| JONES | 35700.00 |
| SCOTT | 36000.00 |
| FORD | 36000.00 |
| KING | 60000.00 |
±-------±---------+

第三十二题:求出员工领导的薪水超过3000的员工名称和领导名称

select e.ename,b.ename as leadername from emp e join emp b 
on e.mgr = b.empno 
where b.sal > 3000;

±------±-----------+
| ename | leadername |
±------±-----------+
| JONES | KING |
| BLAKE | KING |
| CLARK | KING |
±------±-----------+

第三十三题:求部门名称中带s字符的部门员工的工资合计、部门人数(like 与通配符)

%表示可有可无
在这里插入图片描述

select d.dname, sum(e.sal) as totalsal, count(e.ename) as total from emp e 
join dept d 
on e.deptno = d.deptno 
where d.dname like "%s%" 
group by d.deptno;

±------------±---------±------+
| dname | totalsal | total |
±------------±---------±------+
| RESEARCHING | 10875.00 | 5 |
| SALES | 9400.00 | 6 |
±------------±---------±------+

第三十四题:给任职日期超过30年的员工加薪10%(select 是查询,这个是修改update)

为了不再原地改变,我再创建一个emp表(一样的)

create table emp_bak1 as select * from emp;

在这里插入图片描述
开始更新

update emp_bak1 set sal = sal*1.1 
where  (to_days(now())-to_days(hiredate))/365 > 30;
发布了49 篇原创文章 · 获赞 2 · 访问量 1821

猜你喜欢

转载自blog.csdn.net/liuluTL/article/details/105164104
今日推荐