–1、取得每个部门最高薪水的人员名称
–第一步:求出每个部门的最高薪水
–部门编号进行分组,求出最大值
select
xxx
from
emp e
group by e.deptno;
–分组的查询语句显示的字段有两种:分组的字段group by;分组函数
select
e.deptno,max(e.salary) as maxsala
from
emp e
group by e.deptno;
–将以上查询结果当成一个临时表t(deptno,maxsala)
拿t表和emp表做表连接,连接条件是部门编号相等,数据库条件maxsala必须等于员工薪水
select
xxx
from
t
join
emp e
on
t.deptno=e.deptno
where
t.maxsala=e.salary;
–1、取得每个部门最高薪水的人员名称
select
e.deptno,e.name,t.maxsala,e.salary
from
(select
e.deptno,max(e.salary) as maxsala
from
emp e
group by e.deptno)t
join
emp e
on
t.deptno=e.deptno
where
t.maxsala=e.salary
order by
e.deptno – 升序
;
2、哪些人的薪水在部门平均薪水之上
第一步:求出每个部门的平均薪水
根据部门编号分组,求平均值
select
e.deptno,avg(e.salary) as avg_sala
from
emp e
group by
e.deptno;
将以上查询结果当作临时表t(deptno,avg_sala)
2、哪些人的薪水在部门平均薪水之上
select
e.deptno,e.name,t.avg_sala,e.salary
from
(select
e.deptno,avg(e.salary) as avg_sala
from
emp e
group by
e.deptno)t
join
emp e
on
t.deptno=e.deptno
where
e.salary>t.avg_sala
order by
e.deptno
;
3、取得部门中(所有人)平均薪水等级
3.1:取得部门中所有人的平均薪水的等级
第一步:求出部门的平均薪水
select
e.deptno,avg(e.salary) as avg_sala
from
emp e
group by
e.deptno;
将以上查询结果当作临时表t(deptno,avg_sala)
select
t.deptno,t.avg_sala,s.grade
from
(select
e.deptno,avg(e.salary) as avg_sala
from
emp e
group by
e.deptno)t
join
salgrade s
on
t.avg_sala between s.lowsalary and hightsalary
order by
deptno
;
3.2:取得部门中所有人的平均的薪水等级
第一步:求出每个人的薪水等级
select
e.deptno,e.name,s.grade
from
emp e
join
salgrade s
on
e.salary between s.lowsalary and s.hightsalary
order by
e.deptno
;
将以上查询等级当作查询表t(deptno,name,grade)
每个部门平均的薪水等级,部门分组求平均的薪水等级
select
t.deptno,avg(t.grade) as avg_grade
from
(select
e.deptno,e.name,s.grade
from
emp e
join
salgrade s
on
e.salary between s.lowsalary and s.hightsalary
order by
e.deptno)t
group by
t.deptno
;
4、不准用组函数(max),取得最高薪水(给出两种解决方案)
第一种方法:
select
salary
from
emp
order by
salary
desc
limit
1;
第二种方法:
select max(salary)
from emp;
第三种方法:
select 出现笛卡尔积情况,去重操作解决 select 求出最大值 求出最小值 5、取得平均薪水最高的部门的部门编号 第二步:取最高值 第二步:将以上查询结果当作临时表t(deptno,avg_sal) 第三步:然后通过分组having过滤出最大平均薪水的部门编号 6、取得平均薪水最高的部门的部门名称 select 7、求平均薪水的等级最低的/最高的部门的部门名称 第二步:将以上查询结果当作临时表t(dname,deptno,avg_sal)与salgrade 表进行表连接,t.avg_sal between s.lowsalary and s.hightsalary 第三步:求最低和最高值不可以用排序 第五步:求平均薪水的等级最低的部门的部门名称 8、取得比普通员工(员工代码没有在mgr上出现的)的最高薪水还要高的经理人姓名 select * from emp where empno not in (select distinct mgr from emp);-- 查询出来是空,not in 不会自动忽略空值,有null值参与计算 not in 不会自动忽略空值,有null值参与计算,参数值的关系是and 第二步:找到普通员工的最高薪水 第三步:取得比普通员工(员工代码没有在mgr上出现的)的最高薪水还要高的经理人姓名 select name 9、取得薪水最高的前五名员工 10、取得薪水最高的第六到第十名员工 11、取得最后入职的五名员工 12、取得每个薪水等级有多少员工 13、有3个表S(学生表),C(课程表),SC(学生选课表) 第一步:创建表,每个表必须有主键 insert into s(sname) values(‘zhangsan’); create table c( insert into c(cname,cteacher) values (‘jave’,‘吴老师’); create table sc( – 学生和课程多对多的关系,复合主键,是主键的同时也是外键 insert into sc(sno,cno,scgrade) values (1,1,30); 第二步:问题: 2、列出2门以上(含2门)不及格学生的姓名及平均成绩 第三步:找出学生姓名 第四步:平均成绩,根据学号分组,求出每个学号的平均成绩 select 3、即学过1号课程又学过2号课所有学生的姓名-重点:经常考的一道面试题 第二步:既学过1号课程又学过2号课程的学生 select sno from sc where cno=1 and sc.sno in (select sno from sc where cno=2);-学过2号课程的学生编号 第三步:学生姓名 14、列出所有员工(注意:必须使用外连接,内连接空值查询不到)及领导的名字 15、列出受雇日期早于其直接上级的所有员工编号、姓名、部门名称 16、列出部门名称和这些部门的员工信息,同时列出那些没有员工的部门 17、列出至少有5个员工的所有部门 18、列出薪水比“SMITH”多的所有员工信息 第二步: 19、列出所有“CLERK”(办事员)的姓名及其部门名称,部门人数 第一步:找出工作岗位是“CLERK”(办事员)的人 第二步:求每个部门的员工数量,分组 第三步:t1,t2进行匹配 20、列出最低薪水大于1500的各种工作及从事此工作的全部雇员人数 第一步:求出每种工作岗位的最低薪水,按照工作岗位进行分组,求最低值 21、列出在部门“SALES”(销售部)工作的员工的姓名,假定不知道销售部门的部门编号 22、列出薪金高于公司平均薪金的所有员工,所在部门、上级领导、雇员的工资等级 23、列出与“SCOTT”从事相同工作的所有员工及部门名称 24、列出薪金等于部门30中员工的薪金的其他员工的姓名和薪金 25、列出薪金高于在部门30工作的所有员工的薪金的员工姓名和薪金,部门名称 26、列出在每个部门工作的员工数量,平均工资和平均服务期限 select name,(to_days(now())-to_days(hire_date))/365 as serveryear from emp; --服务年限 第二步: 27、列出所有员工的姓名、部门名称和工资-- 所有修饰的是后面的名词 28、列出所有部门的详细信息和人数 第三步: 29、列出各种工作的最低工资及从事此工作的雇员姓名 第二步:将以上查询结果当作临时表t(job,minsal) 30、列出各个部门MANAGER的最低薪金 select 32、求出员工的领导的薪水超过3000的员工名称和领导名称 33、求部门名称中带“S”字符的部门员工的工资合计,部门人数 34、给任职日期超过30年的员工加薪10% 网易云课堂《经典MYSQL面试题》
a.salary
from
emp a
join
emp b
on
a.salary
distinct a.salary
from
emp a
join
emp b
on
a.salary
select salary from emp where salary not in
(select
distinct a.salary
from
emp a
join
emp b
on
a.salary
select salary from emp where salary not in
(select
distinct a.salary
from
emp a
join
emp b
on
a.salary>b.salary);
第一步:求出每个部门平均薪水
select
e.deptno,avg(salary) as avg_sal
from
emp e
group by
e.deptno;
select
e.deptno,avg(salary) as avg_sal
from
emp e
group by
e.deptno
order by
avg_sal desc
limit 1 – 排序行不通,如果出现两个部门是最大值
;
select
max(t.avg_sal)
from
(select
e.deptno,avg(salary) as avg_sal
from
emp e
group by
e.deptno)t;
select
e.deptno,avg(salary)
from
emp e
group by
e.deptno
having
avg(salary) like – 等于号查出来是空
(select
max(t.avg_sal)
from
(select
e.deptno,avg(salary) as avg_sal
from
emp e
group by
e.deptno)t);
e.deptno,d.dname,avg(e.salary) as avg_sal
from
emp e
join
dept d
on
e.deptno=d.depto
group by
e.deptno,d.dname-- 分组编号和分组名称是一对一的,所以可以放在一起分组
having
avg_sal like – 等于号查出来是空
(select
max(t.avg_sal) as max_avg_sal
from
(select
e.deptno,avg(e.salary) as avg_sal
from
emp e
group by
e.deptno)t);
第一步:部门的平均薪水
select
e.deptno,avg(e.salary) as avg_sal
from
emp e
join
dept d
on
e.deptno=d.depto
group by
e.deptno;
每个部门平均薪水等级
select
t.deptno,t.dname,s.grade
from
(select
e.deptno,avg(e.salary) as avg_sal,d.dname
from
emp e
join
dept d
on
e.deptno=d.depto
group by
e.deptno)t
join
salgrade s
on
t.avg_sal between s.lowsalary and hightsalary;
将以上查询结果当作一张临时表t
查出最低等级
select min(t.grade) as mingrade from (select
t.deptno,t.dname,s.grade
from
(select
e.deptno,avg(e.salary) as avg_sal,d.dname
from
emp e
join
dept d
on
e.deptno=d.depto
group by
e.deptno)t
join
salgrade s
on
t.avg_sal between s.lowsalary and hightsalary
)t;
第四步:having必须用在group by 后,是在分组之后对数据不满意再进行过滤
where用在group by 之前,所以此处用where
select
t.deptno,t.dname,s.grade
from
(select
e.deptno,avg(e.salary) as avg_sal,d.dname
from
emp e
join
dept d
on
e.deptno=d.depto
group by
e.deptno)t
join
salgrade s
on
t.avg_sal between s.lowsalary and hightsalary
where
s.grade=3
;
select
t.deptno,t.dname,s.grade
from
(select
e.deptno,avg(e.salary) as avg_sal,d.dname
from
emp e
join
dept d
on
e.deptno=d.depto
group by
e.deptno)t
join
salgrade s
on
t.avg_sal between s.lowsalary and hightsalary
where
s.grade=(select min(t.grade) as mingrade from (select
t.deptno,t.dname,s.grade
from
(select
e.deptno,avg(e.salary) as avg_sal,d.dname
from
emp e
join
dept d
on
e.deptno=d.depto
group by
e.deptno)t
join
salgrade s
on
t.avg_sal between s.lowsalary and hightsalary
)t)
;
第一步:找出普通员工(员工代码没有出现在mgr上的)
1.1先找出mgr 有哪些人
select distinct mgr from emp;
1.2没有出现在mgr上
select * from emp where empno in (select distinct mgr from emp);-- in会自动忽略null
in 会自动忽略空值,参数值的关系是or
使用not in 需要手动忽略空值
1.2正确语句
select * from emp where empno not in (select distinct mgr from emp where mgr is not null);
select max(salary) as max_sal
from emp
where empno not in (select distinct mgr from emp where mgr is not null);
select name from emp where salary>1600;
from emp
where salary>
(select max(salary) as max_sal
from emp
where empno not in (select distinct mgr from emp where mgr is not null));
select * from emp order by salary desc limit 0,5;
知识点:
order by 这个关键字,单个字段排序,多个字段排序需要半角逗号隔开,默认的排序方式升序asc
limit 截取前几行或者中间几行参数,两个参数,第一个是从哪里开始,第二个是截取长度,limit 还有分页的功能
select * from emp order by salary desc limit 5,5;-- 从第五个开始,截取五个
知识点:
limit 的截取用法
第一步:按照时间来排序,入职的时间越晚,值越大
select * from emp order by hire_date desc limit 5;
知识点:
排序不仅仅可以通过数字,也可以通过日期类
第一步:查询出每个员工的薪水等级
select
e.name,s.grade
from
emp e
join
salgrade s
on
e.salary between s.lowsalary and s.hightsalary
order by
s.grade;
第二步:按照等级值进行分组,求出每个等级有多少个人
将以上查询结果当作临时表t(name,grade)
select
t.grade,count(t.name) as totaltemp
from
(select
e.name,s.grade
from
emp e
join
salgrade s
on
e.salary between s.lowsalary and s.hightsalary
order by
s.grade)t
group by
t.grade
order by
t.grade
;
S(SNO,SNAME)代表(学号,姓名)
C(CNO,CNAME,CTEACHER)代表(课号,课名,教师)
SC(SNO,CNO,SCGRADE)代表(学号,课号,成绩)
问题:
1、找出没选择过“黎明”老师的所有学生姓名
2、列出2门以上(含2门)不及格学生的姓名及平均成绩
3、即学过1号课程又学过2号课所有学生的姓名
create table s(
sno int(4) primary key auto_increment,
sname varchar(32)
);
insert into s(sname) values(‘lisi’);
insert into s(sname) values(‘wangwu’);
insert into s(sname) values(‘zhaoliu’);
cno int(4) primary key auto_increment,
cname varchar(32),
cteacher varchar(32)
);
insert into c(cname,cteacher) values (‘c++’,‘张老师’);
insert into c(cname,cteacher) values (‘jave’,‘张老师’);
insert into c(cname,cteacher) values (‘mysql’,‘郭老师’);
insert into c(cname,cteacher) values (‘oracle’,‘黎明’);
sno int(4),
cno int(4),
scgrade double(3,1) – double 三个有效数,一个小数
);
– 一张表里只能有一个主键,但是可以有多个外键
– 疑惑:复合主键和外键不会使用语句添加
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,90);
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,80);
insert into sc(sno,cno,scgrade) values (3,4,50);
insert into sc(sno,cno,scgrade) values (4,4,80);
/*1、找出没选择过“黎明”老师的所有学生姓名
首先对表进行理解,有哪些字段
2、列出2门以上(含2门)不及格学生的姓名及平均成绩
3、即学过1号课程又学过2号课所有学生的姓名
*/
1、找出没选择过“黎明”老师的所有学生姓名
第一步:先找出选过黎明老师的学生编号->黎明老师的授课编号
select cno from c where cteacher=‘黎明’;
select sno from sc where cno =(select cno from c where cteacher=‘黎明’);
select * from s where sno not in (select sno from sc where cno =(select cno from c where cteacher=‘黎明’));
第一步:求出不及格的学生
select * from sc where scgrade<60;
第二步:在分组前能过滤就先过滤,然后进行分组
select
sc.sno,count(*) as studentnum – count的使用
from
sc
where
scgrade<60
group by
sc.sno
having
studentnum>=2;
t1
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;
t2
select
sc.sno,avg(sc.scgrade) as avgscgrade
from
sc
group by
sc.sno;
第五步:第三步和第四步的结果合并
t1.sname,t2.avgscgrade
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) as avgscgrade
from
sc
group by
sc.sno)t2
on
t1.sno=t2.sno;
第一步:学过1号课程的学生,学过2号课的学生
select sno from sc where cno=1;
select sno from sc where cno=2;
select sno from sc where cno=1 and cno=2;- 空集,该方法错误,没有课程编号既等于1又等于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
e.name,b.name as leadername
from
emp e
left join – 使用join,查询结果少了KING,不可以使用join内连接,要使用外连接,外连接查到的条数永远大于内连接
emp b
on
e.empno=b.mgr;
考点:多张表连接
select
e.empno,e.name,d.dname
from
emp e
join
emp b
on
e.mgr=b.empno
join
dept d
on
e.deptno=d.depto
where
e.hire_date
第一步:求出部门名称和所对应的员工信息,使用join,但是没有求出那些没有员工的部门,所以使用右连接
select
d.dname,e.*
from
emp e
right join – 少了一个OPERATIONS,所以使用外连接,使用右连接
dept d
on
e.deptno=d.depto;
第一步:先求出每个部门的员工数量,根据部门来分组
select
e.deptno,count(e.name) as totalemp
from
emp e
group by
e.deptno;
第二步:对分组后的数据不满意,进行过滤,使用having
select
e.deptno,count(e.name) as totalemp
from
emp e
group by
e.deptno
having
totalemp>=5
;
考点:子查询
第一步:求出“SMITH”的薪水
select salary from emp where name=‘SMITH’;
select * from emp where salary > (select salary from emp where name=‘SMITH’);
t1
select
d.depto,d.dname,e.name
from
emp e
join
dept d
on
e.deptno=d.depto
where
e.job=‘CLERK’;
t2
select
e.deptno,count(e.name) as totalemp
from
emp e
group by
e.deptno;
select
t1.depto,t1.name,t2.totalemp
from
(select
d.depto,d.dname,e.name
from
emp e
join
dept d
on
e.deptno=d.depto
where
e.job=‘CLERK’)t1
join
(select
e.deptno,count(e.name) as totalemp
from
emp e
group by
e.deptno)t2
on
t1.depto=t2.deptno;
select
e.job,min(e.salary) as minsal
from
emp e
group by
e.job
having
minsal>1500;
第二步:考点:聚合函数,可以多次使用分组函数
select
e.job,min(e.salary) as minsal,count(e.name) as totalemp
from
emp e
group by
e.job
having
minsal>1500;
第一步:求出销售部的部门编号
select depto from dept where dname=‘SALES’;
第二步:列出在部门编号30工作的员工的姓名,=后面SQL 语句只能是一个值
考点:子查询,前面主句中只能是一个字段,后面子查询语句中只能是一个值,两个字段没办法进行比较,也没办法进行数据计算
select e.name from emp e where e.deptno=(select depto from dept where dname=‘SALES’);
第一步:求出公司的平均薪水
select avg(salary) as avgsal from emp;
第二步:
select
d.dname,e.name,b.name as leadername,s.grade
from
emp e
join
dept d
on
e.deptno=d.depto
left join
emp b
on
e.mgr=b.empno
join
salgrade s
on
e.salary between s.lowsalary and s.hightsalary
where
e.salary>(select avg(salary) as avgsal from emp);
第一步:找出“SCOTT”的工作岗位job
select job from emp where name=‘SCOTT’;
第二步:
select
d.dname,e.*
from
emp e
join
dept d
on
e.deptno=d.depto
where
e.job=(select job from emp where name=‘SCOTT’);
第一步:部门30中员工的薪水有哪几种值
select distinct salary from emp where deptno=30;
第二步:
select name,salary from emp where salary in (select distinct salary from emp where deptno=30) and deptno <>30;
第一步:先找出部门30的最高薪水
select max(salary) as maxsal from emp where deptno=30;
第二步:
select
d.dname,e.name,e.salary
from
emp e
join
dept d
on
e.deptno=d.depto
where
e.salary>(select max(salary) as maxsal from emp where deptno=30);
第一步:求出平均服务期限
to_days (日期类型)-》天数
now() 函数
获取数据库系统当前时间的函数
天数除以365能求出大约的年数
select to_days(now())/365;
平均服务年限
select avg((to_days(now())-to_days(hire_date))/365) as avgserveryear from emp;
select
e.deptno,
count(e.name) as totalemp,
avg(e.salary) as avgsal,
avg((to_days(now())-to_days(hire_date))/365) as avgserveryear
from
emp e
group by
e.deptno;
疑点:左连接,右连接,内连接的使用
select
d.dname,e.name,e.salary
from
emp e
right join – 少一个null,所以使用右连接
dept d
on
e.deptno=d.depto;
第一步:先求出每个部门的人数
select
e.deptno,count(e.name) as totalemp
from
emp e
group by
e.deptno;
第二步:
select
e.deptno,count(e.name) as totalemp,d.dname,d.local
from
emp e
right join – 差一个40,右连接让部门信息表全部显示出来
dept d
on
e.deptno=d.depto
group by
e.depto,d.dname,d.local; – 查不来是null,把e.deptno改成d.depto
select
d.depto,count(e.name) as totalemp,d.dname,d.local
from
emp e
right join
dept d
on
e.deptno=d.depto
group by
d.depto,d.dname,d.local;
第一步:每种工作岗位的最低薪水
select
e.job,min(e.salary) as minsal
from
emp e
group by
e.job;
select
e.name
from
emp e
join
(select
e.job,
min(e.salary) as minsal
from
emp e
group by
e.job
) t
on
e.job=t.job
where
e.salary=t.minsal;
select
e.deptno,min(e.salary) as minsal
from
emp e
where
e.job=‘MANAGER’
group by
e.deptno;31、列出所有员工的年工资,按年薪从低到高排序
select
name,
12*(salary+ifnull(comm,0)) as yearsal --ifnull(comm,0)年薪的计算错误
from
emp
order by
yearsal;
name,
12*salary as yearsal
from
emp
order by
yearsal;
select
e.name,b.name as leadername
from
emp e
join
emp b
on
e.mgr=b.empno
where
b.salary>3000;
第一步:先求出部门名称带“S”
select
d.dname,
sum(e.salary) as sumsal,
count(e.name) as totalemp
from
emp e
join
dept d
on
e.deptno=d.depto
where
d.dname like ‘%s%’
group by
d.dname;
select 永远不会改变底层数据库的数据,是显示出的数据
show tables;
select * from emp;
drop table emp_bak1;
create table emp_bak1 as select * from emp;-- 备份
update emp_bak1 set salary = salary *1.1 where (to_days(now())-to_days(hire_date))/365>30;
select * from emp_bak1;