(sql语句试题练习及 参考答案解题思路+个人解题思路)
SQL字段说明及数据
=======================================================================
一、部门表字段描述:
dp_no 部门ID
dp_name 部门名称
dp_loc 部门所在地
二、员工表字段说明:
eNo 员工编号
eName 员工姓名
eJob 员工职责
emgr 上司编号
eHiredate 入职时间
eSal 工资
ecomm 扣税
dp_no 部门ID
创建数据库及数据表
CREATE DATABASE IF NOT EXISTS SQLTEST;
CREATE TABLE IF NOT EXISTS dept(
dp_no int(10) not null primary key,
dp_name varchar(25),
dp_loc varchar(25)
);
CREATE TABLE IF NOT EXISTS EMP(
eNo int(25) not null primary key,
eName varchar(45),
eJob varchar(45),
emgr int(25),
eHiredate date,
eSal int(45),
ecomm int(45),
dp_no int(25)
);
添加dept表数据:
insert into dept(dp_no, dp_name, dp_loc) values (10, 'ACCOUNTING', 'NEW YORK');
insert into dept(dp_no, dp_name, dp_loc) values (20, 'RESEARCH', 'DALLAS');
insert into dept(dp_no, dp_name, dp_loc) values (30, 'eSalES', 'CHICAGO');
insert into dept(dp_no, dp_name, dp_loc) values (40, 'OPERATIONS', 'BOSTON');
commit;
添加EMP表数据: eNo, eName, eJob, emgr, eHiredate, eSal, ecomm, dp_no
insert into EMP(eNo, eName, eJob, emgr, eHiredate, eSal, ecomm, dp_no) values (7369, 'SMITH', 'CLERK', 7902, '1980-12-17', 800, null, 20);
insert into EMP(eNo, eName, eJob, emgr, eHiredate, eSal, ecomm, dp_no) values (7499, 'ALLEN', 'eSalESMAN', 7698,'1981-02-20', 1600, 300, 30);
insert into EMP(eNo, eName, eJob, emgr, eHiredate, eSal, ecomm, dp_no) values (7521, 'WARD', 'eSalESMAN', 7698, '1981-02-22', 1250, 500, 30);
insert into EMP(eNo, eName, eJob, emgr, eHiredate, eSal, ecomm, dp_no) values (7566, 'JONES', 'MANAGER', 7839, '1981-04-02' , 2975, null, 20);
insert into EMP(eNo, eName, eJob, emgr, eHiredate, eSal, ecomm, dp_no) values (7654, 'MARTIN', 'eSalESMAN', 7698, '1981-09-28' , 1250, 1400, 30);
insert into EMP(eNo, eName, eJob, emgr, eHiredate, eSal, ecomm, dp_no) values (7698, 'BLAKE', 'MANAGER', 7839, '1981-05-01' , 2850, null, 30);
insert into EMP(eNo, eName, eJob, emgr, eHiredate, eSal, ecomm, dp_no) values (7782, 'CLARK', 'MANAGER', 7839, '1981-06-09' , 2450, null, 10);
insert into EMP(eNo, eName, eJob, emgr, eHiredate, eSal, ecomm, dp_no) values (7788, 'SCOTT', 'ANALYST', 7566, '1987-04-19' , 3000, null, 20);
insert into EMP(eNo, eName, eJob, emgr, eHiredate, eSal, ecomm, dp_no) values (7839, 'KING', 'PRESIDENT', null, '1981-11-17' , 5000, null, 10);
insert into EMP(eNo, eName, eJob, emgr, eHiredate, eSal, ecomm, dp_no) values (7844, 'TURNER', 'eSalESMAN', 7698, '1981-09-08' , 1500, 0, 30);
insert into EMP(eNo, eName, eJob, emgr, eHiredate, eSal, ecomm, dp_no) values (7876, 'ADAMS', 'CLERK', 7788, '1987-05-23' , 1100, null, 20);
insert into EMP(eNo, eName, eJob, emgr, eHiredate, eSal, ecomm, dp_no) values (7900, 'JAMES', 'CLERK', 7698, '1981-12-03' , 950, null, 30);
insert into EMP(eNo, eName, eJob, emgr, eHiredate, eSal, ecomm, dp_no) values (7902, 'FORD', 'ANALYST', 7566, '1981-12-02' , 3000, null, 20);
insert into EMP(eNo, eName, eJob, emgr, eHiredate, eSal, ecomm, dp_no) values (7934, 'MILLER', 'CLERK', 7782, '1982-01-23' , 5000, null, 10);
操作:
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SQL基本操作案例
=======================================================================
老师给的问题及解题思路
【1】. 查询出JONES的领导是谁(JONES向谁报告)。
子查询(效率低):
select
eName
from
EMP where eNo in(select emgr from EMP where eName='JONES');
Join写法(高效):
select
e2.eName
from(select emgr from EMP where eName='JONES') e1
left join EMP e2
on e1.emgr=e2.eNo;
=======================================================================
【2】.JONES领导谁。(谁向JONES报告)。
子查询(效率低):
select
eName
from EMP
where emgr in (select emgr from EMP where eName='JONES');
Join写法(高效):
select
e2.eName
from(select eNo from EMP where eName='JONES') e1
left join EMP e2
on e1.eNo=e2.emgr;
=======================================================================
【3】. 查询各职位的员工工资的最大值,最小值,平均值,总和
(问题:下面好像是各部门的,上面的各职位的呢?-->eJob,各职位就应该更简单,按职位分组)
第一步:
select eJob,max(eSal) as '最高薪资' from EMP group by eJob;
select eJob,min(eSal) as '最低薪资' from EMP group by eJob;
select eJob,avg(eSal) as '平均薪资' from EMP group by eJob;(要想保留小数点,round 里面不能写as,写到外面);
第二步:
select
eJob,
max(eSal) as '最低薪资',
min(eSal) as '最低薪资',
avg(eSal) as'平薪资均',
sum(eSal) as'总和'
from EMP
group by eJob;
====================================================================
【4】. 选择具有各个eJob的员工人数(提示:对eJob进行分组,题目不太清楚觉得。。。)
select
eJob as '职务',
count(eJob) as '各职务人数'
from EMP
group by eJob;
【5】. 查询员工最高工资和最低工资的差距,列名为DIFFERENCE;
select max(eSal)-min(eSal) as'DIFFERENCE' from EMP;
====================================================================
【6】. 查询各个管理者属下员工的最低工资,其中最低工资不能低于800,没有管理者的员工
不计算在内
====================================================================
【7】. 查询所有部门的部门名字dp_name,所在位置dp_loc,员工数量和工资平均值;
第一步:各部门编号、员工数量和工资平均值,作为一表,用Join思想!!!
select dp_no,count(eNO) as'员工数量',avg(eSal) as'工资平均' from EMP group by dp_no;
B、A、各部门编号、员工数量和工资平均值
select dp_name as'部门名',dp_loc as'位置',nums as'员工数量',avgeSal as'平均工资' from
(select dp_no as no,count(eNO) as nums ,avg(eSal) as avgeSal from EMP group by dp_no) e
left join dept d on d.dp_no=e.no;
select
d.dp_name as'部门名',
d.dp_loc as'位置',
e.nums as'员工数量',
e.avgeSal as'平均工资'
from dept d
left join (select dp_no as no,count(eNO) as nums ,avg(eSal) as avgeSal from EMP group by dp_no) e
on d.dp_no=e.no;
高效:和我写的上面写的有什么区别???
select
d.dp_name,
d.dp_loc,
count(eNO),
round(if(avg(eSal) is null,0,avg(eSal)),2) as'平均薪资'
from dept d
left join EMP e
on d.dp_no=e.dp_no
group by e.dp_no;
###round(xxx,2)保留两位小数点
round(if(avg(eSal) is null,0,avg(eSal)),2) as'平均薪资'
#####判断avg(eSal) is null,0,avg(eSal)为空时为0,否则用自己本身avg(eSal)
if(avg(eSal) is null,0,avg(eSal))
====================================================================
【8】. 查询和scott相同部门的员工姓名eName和雇用日期eHiredate
普通写法(效率低):
select
e.eName,
e.eHiredate
from EMP e
where dp_no=(select dp_no from EMP where eName='SCOTT');
Join写法(高效):
select
e2.eName,
e2.eHiredate
from (select dp_no from EMP where eName='SCOTT') e1
left join EMP e2
on e1.dp_no=e2.dp_no;
====================================================================
【9】. 查询工资比公司平均工资高的所有员工的员工号eNo,姓名eName和工资eSal。
子查询(效率低):
select eNo as'编号',eName as'姓名',eSal as'薪资' from EMP where
eSal>(select avg(eSal) from EMP);
Join查询(高效):
select
e2.eNO,
e2.eName,
e2.eSal
from (select avg(eSal) as avg from EMP) e1
left join EMP e2
on e1.avg<=e2.eSal;
====================================================================
【10】. 查询和姓名中包含字母u的员工在相同部门的员工的员工号eNo和姓名eName
子查询(效率低);
select
eNo as'编号',
eName as'姓名'
from EMP
where dp_no in (select dp_no from EMP Where eName like '%u%');
如果in写为=号,返回的结果rows超过一行时会报下面错误,所以最好用in!
ERROR 1242 (21000): Subquery returns more than 1 row
Join查询1(高效,包括又u字母的名字也都被查出来了):
select
e2.eNo,
e2.eName
from( select dp_no from EMP where eName like '%u%') e1
left join EMP e2
on e1.dp_no=e2.dp_no;
Join查询2(高效,去掉包括有u字母的名字):
select
e2.eNo,
e2.eName
from(select dp_no,eName from EMP where eName like '%u%') e1
left join EMP e2
on e1.dp_no=e2.dp_no
where e1.eName!= e2.eName;
=================================================================
【11】. 查询在部门dp_loc为newYork的部门工作的员工的员工姓名eName,
部门名称dp_name和岗位名称eJob
子查询:
select
eName as'姓名',
dp_name as'部门',
eeJob as'职位'
from EMP e ,dept d
where e.dp_no =d.dp_no and d.dp_dp_loc='NEW YORK';
select
eName as'姓名',
dp_name as'部门',
eeJob as'职位'
from dept d
left join EMP e
on e.dp_no =d.dp_no
where d.dp_dp_loc='NEW YORK';
select
e.eName as'姓名',
d.dp_name as'部门',
e.eJob as'职位'
from(select dp_no,dp_name from dept where dept.dp_loc='NEW YORK') d
left join EMP e
on e.dp_no =d.dp_no;
====================================================================
【12】. 查询管理者是king的员工姓名eName和工资eSal
select
eName as '姓名',
eSal as '薪资'
from EMP
where emgr in( select eNo from EMP where eName='KING');
select
e2.eName,
e2.eSal
from (select eNo from EMP where eName='KING') e1
left join EMP e2
on e1.eNo=e2.emgr;
====================================================================
【13】. 显示ACCOUNTING部门有哪些职位
普通查询:
select
eJob as'职位'
from dept d,EMP e
where d.dp_no=e.dp_no and d.dp_name='ACCOUNTING';
Join写法:
select
e2.eJob as'职位'
from(select dp_no from dept where dp_name='ACCOUNTING') d
left join EMP e2
on d.dp_no=e2.dp_no
====================================================================
【14】. 各个部门中工资大于1500的员工人数及部门名称
select
d.dp_name,
e.num as '薪资大于1500的各部门人数'
from (select dp_no ,count(eNo) as num from EMP Where eSal>1500 group by dp_no) e
left join dept d
on e.dp_no=d.dp_no;
====================================================================
【15】. 哪些员工的工资,高于整个公司的平均工资,列出员工的名字和工资(降序)
子查询:
select
e.eName,
e.eSal
from EMP e
where eSal > (select avg(eSal) from EMP)
order by eSal desc;
Join写法:
select
e2.eName as '高于整个公司的平均工资的员工姓名',
e2.eSal as '对应的薪资'
from(select avg(eSal) as avg from EMP) e1
left join EMP e2
on e2.eSal>e1.avg
order by e2.eSal desc;
====================================================================
【16】. 所在部门平均工资高于1500的员工名字
(如果部门的平均工资高于1500,输出这个部门所有员工姓名)
select
e2.eName as '员工姓名'
from(select dp_no,avg(eSal) as avg from EMP group by dp_no having avg>1500) e1
left join EMP e2
on e2.dp_no=e1.dp_no;
select dp_no,avg(eSal) as avg from EMP group by dp_no having avg>1500
只能用having 不能用where,having是在做分组之后过滤
====================================================================
【17】. 列出各个部门中工资最高的员工的信息:员工名字、部门名称、工资(有点问题哦)
子查询:
select
eName as '姓名',
dp_no as '部门号',
eSal as '薪资'
from EMP where eSal in (select max(eSal) from EMP group by dp_no);
Join写法:
select
e.eName as '姓名',
d.dp_name as '部门名称',
e.es as '薪资'
from dept d
left join (select eName,dp_no,max(eSal) as es from EMP group by dp_no) e
on d.dp_no = e.dp_no;
====================================================================
【18】. 哪个部门的平均工资是最高的,列出部门号、平均工资
select
dp_no,
avg(eSal) as esal
from EMP
group by dp_no
order by esal desc
limit 1;
有两个以上的部门平均薪资都是最高的怎么办?
====================================================================
max怎么实现?思路:分组找到各部门平均薪资、部门号表e1,在从中找出最大值做表2为左表
又用类似于表e1作为右边表
select
e3.dp_no,
e3.avg
from
(
select
max(e1.avg) as max
from(select dp_no,avg(eSal) as avg from EMP group by dp_no) e1
)e2
left join(select dp_no,avg(eSal) as avg from EMP group by dp_no) e3
on e2.max=e3.avg;
select
from(select
e1.avg as avg_max
from(select dp_no,avg(eSal) as avg from EMP group by dp_no) e1) e2
left join
---------------------------------------------------------------------------------------------------
个人解题思路:
-- 1.查询出JONES的领导是谁
SELECT emgr FROM EMP WHERE eName='JONES' -- 根据员工姓名查询领导编号
SELECT eName FROM EMP WHERE eNo=7839 -- 根据员工编号查询员工姓名
-- 合并
SELECT eName FROM EMP WHERE eNo=(
SELECT emgr FROM EMP WHERE eName='JONES')
-- 2.JONES领导谁。
SELECT eNo FROM EMP WHERE eName='JONES' -- 根据员工姓名查找员工编号
SELECT eNo FROM EMP WHERE emgr=7566 -- 根据员工编号查找员工姓名
SELECT eName FROM EMP WHERE eNo IN(
SELECT eNo FROM EMP WHERE emgr=7566 ) -- 根据上司编号查找员工姓名
SELECT eName FROM EMP WHERE eNo IN(
SELECT eNo FROM EMP WHERE emgr=
(SELECT eNo FROM EMP WHERE eName='JONES') ) -- 根据上司姓名查找员工
-- 3.查询各职位的员工工资的最大值,最小值,平均值,总和
SELECT eSal,eJob FROM EMP -- 各职位员工工资
SELECT MAX(eSal),eJob FROM EMP GROUP BY eJob -- 各职位员工工资最大值
SELECT MIN(eSal),eJob FROM EMP GROUP BY eJob -- 各职位员工工资最小值
SELECT AVG(eSal),eJob FROM EMP GROUP BY eJob -- 各职位员工工资平均值
SELECT SUM(eSal),eJob FROM EMP GROUP BY eJob -- 各职位员工工资总和
-- 4.选择具有各个eJob的员工人数
-- 理解:查询选择各eJob的员工人数
SELECT COUNT(eNo),eJob FROM EMP GROUP BY eJob
-- 5.查询员工最高工资和最低工资的差距,列名为DIFFERENCE
SELECT MAX(eSal) FROM EMP -- 查询员工最高工资
SELECT MIN(eSal) FROM EMP -- 查询员工最低工资
SELECT (MAX(eSal) - MIN(eSal))AS DIFFERENCE FROM EMP
-- 6.查询各个管理者属下员工的最低工资,其中最低工资不能低于800,没有管理者的员工
-- 不计算在内
-- 首先查询管理者都有哪些员工,再计算员工的最低工资,并且最低工资不能低于800,以管理者编号分组
SELECT emgr FROM EMP GROUP BY emgr -- 查询各个管理者编号
-- 通过管理者编号查询员工编号,员工姓名,管理者编号,员工最低工资,以管理者编号分组
SELECT eNo,eName,emgr,MIN(eSal) FROM EMP WHERE emgr IN(
SELECT emgr FROM EMP GROUP BY emgr) GROUP BY emgr HAVING MIN(eSal)>=800
-- 7.查询所有部门的部门名字dp_name,所在位置dp_loc,员工数量和工资平均值
-- 查询所有部门的部门名字,所在位置
SELECT dp_name,dp_loc FROM dept
-- 根据部门id查询员工数量
SELECT COUNT(eNo) FROM
-- 内连接查询,分组查询
SELECT d.dp_name,d.dp_loc,COUNT(eNo),AVG(eSal) FROM EMP e INNER JOIN dept d
ON d.dp_no =e.dp_no GROUP BY d.dp_no
-- 8.查询和scott相同部门的员工姓名eName和雇用日期eHiredate
-- 查询scott所在部门id
SELECT dp_no,eName FROM EMP WHERE eName='scott'
-- 根据部门id查询员工姓名和雇佣日期
SELECT eName,eHiredate FROM EMP WHERE dp_no IN(
SELECT dp_no FROM EMP WHERE eName='scott')
-- 9.查询工资比公司平均工资高的所有员工的员工号eNo,姓名eName和工资eSal
SELECT AVG(eSal) FROM EMP -- 查询公司平均工资
SELECT eSal FROM EMP GROUP BY eNo -- 查询公司员工工资
SELECT eNo FROM EMP HAVING eSal>AVG(eSal) -- 错
SELECT eNo,eName,eSal FROM EMP WHERE eSal>(SELECT AVG(eSal) FROM EMP) -- 正确
-- 10.查询和姓名中包含字母u的员工在相同部门的员工的员工号eNo和姓名eName
-- 查询姓名中包含字母u的员工及所在部门id
SELECT eName,eNo,dp_no FROM EMP WHERE eName LIKE 'u%' OR eName LIKE '%u%' OR eName LIKE '%u'
-- 根据部门id查询该部门中的员工号和姓名
SELECT eName,eNo FROM EMP WHERE dp_no=30
-- 合并
SELECT eName,eNo FROM EMP WHERE dp_no IN(
SELECT dp_no FROM EMP WHERE eName LIKE 'u%' OR eName LIKE '%u%' OR eName LIKE '%u')
-- 11.查询在部门dp_loc为newYork的部门工作的员工的员工姓名eName,
-- 部门名称dp_name和岗位名称eJob
-- 查询部门名称为newYork的部门id
SELECT dp_no FROM dept WHERE dp_loc='NEW YORK'
-- 查询部门dp_loc为newYork的部门工作的员工的员工姓名eName
SELECT eName FROM EMP WHERE dp_no=10
-- 合并
SELECT eName FROM EMP WHERE dp_no IN(
SELECT dp_no FROM dept WHERE dp_loc='NEW YORK')
-- 12.查询管理者是king的员工姓名eName和工资eSal
-- 查询king的员工编号
SELECT eNo FROM EMP WHERE eName='KING' -- 7839
-- 查询上司编号是7839的员工姓名,工资eSal
SELECT eName,eSal FROM EMP WHERE emgr=7839
-- 合并
SELECT eName,eSal FROM EMP WHERE emgr IN(
SELECT eNo FROM EMP WHERE eName='KING')
-- 13.显示ACCOUNTING部门有哪些职位
-- 查询ACCOUNTING部门的部门id
SELECT dp_no FROM dept WHERE dp_name='ACCOUNTING' -- 10
-- 查询部门id为10的职位有哪些
SELECT eJob FROM EMP WHERE dp_no=10
-- 合并
SELECT eJob FROM EMP WHERE dp_no IN(
SELECT dp_no FROM dept WHERE dp_name='ACCOUNTING')
-- 14.各个部门中工资大于1500的员工人数及部门名称
-- 查询工资大于1500的员工编号和部门编号
SELECT eNo,dp_no FROM EMP WHERE eSal>1500
-- 查询各个部门编号工资大于1500的员工人数
SELECT COUNT(eNo),dp_no FROM EMP WHERE eSal>1500 GROUP BY dp_no
-- 根据部门编号查询部门名称
SELECT dp_name FROM dept WHERE dp_no=10
-- 使用内连接查询,分组查询,条件查询
SELECT COUNT(eNo),d.dp_name FROM EMP e INNER JOIN dept d ON d.dp_no=e.dp_no
WHERE eSal>1500 GROUP BY d.dp_no
-- 15.哪些员工的工资,高于整个公司的平均工资,列出员工的名字和工资(降序)
-- 同第九题
SELECT eNo,eName,eSal FROM EMP WHERE eSal>(SELECT AVG(eSal) FROM EMP) ORDER BY eSal DESC
-- 16.所在部门平均工资高于1500的员工名字,部门编号
SELECT eNo,dp_no FROM EMP WHERE eSal>1500
-- +部门名字
SELECT e.eName,e.eSal,d.dp_name FROM EMP e INNER JOIN dept d ON d.dp_no=e.dp_no
GROUP BY e.eNo HAVING AVG(eSal)>1500
-- 17.列出各个部门中工资最高的员工的信息:员工名字、部门名称、工资
-- 各部门工资最高的员工编号
SELECT MAX(eSal),dp_no,eName FROM EMP GROUP BY dp_no
-- 内连接,分组查询,聚合函数
SELECT MAX(eSal),eName,d.dp_name,d.dp_no FROM EMP e INNER JOIN dept d ON e.dp_no=d.dp_no GROUP BY d.dp_no
-- 18.哪个部门的平均工资是最高的,列出部门号、平均工资
-- 查询各部门平均工资
SELECT AVG(eSal) FROM EMP GROUP BY dp_no
-- 查询平均工资最高的部门号,最高平均工资
SELECT MAX(b),a.dp_no FROM (SELECT AVG(eSal)AS b,dp_no FROM EMP GROUP BY dp_no)AS a
-- +部门名称
SELECT MAX(b),a.dp_no,d.dp_name FROM (SELECT AVG(eSal)AS b,dp_no FROM EMP GROUP BY dp_no)AS a INNER JOIN dept d ON d.dp_no=a.dp_no