SQL语句的解题顺序
- 单表 or 多表
- 单表
单表 是否需要分组,分组是否分组前需要条件where,分组后是否需要having
where 范围 列表 模糊查询
group by 后的字段 和select后一致,聚合函数除外
having
order
- 多表
连接 or 子查询
几张表的连接 顺序是什么 以要求的内容为主
...
解题09-10
- 1.统计各部门男女人数,要求显示出部门名称
select d.name,t.sex,count(eid) as '人数',count(eid) from (select distinct sex from employee)
t left join department d on 1=1 left
join employee e on e.did=d.did and e.sex=t.sex group by d.name,t.sex
- 查询结果其实也是一张表
select distinct sex from employee
- 2.找出技术组长入职后一年职员工
select e1.name,e1.pid,e1.jointime,e2.name,e2.jointime
from position p join employee e1 on p.pid=e1.pid
join employee e2 on 1=1
where p.name = '技术组长' and timestampdiff(YEAR,e1.jointime,e2.jointime) =1
所有的子查询都能改写成连接,反之不能
3.找出掌握了驾驶技能的员工名单
select * from employee e1 left join es on e1.eid=es.eid
left join skill s on es.sid = s.sid
where s.descript like '驾驶%'
- 4.统计各部门掌握了驾驶技能员工人数
select d.did,d.name,count(t.did) from department d left join
(select e.did from skill s join es on es.sid = s.sid and s.descript like '驾驶%'
join employee e on e.eid = es.eid) t on t.did = d.did
group by d.did,d.name
- 5.统计各班身高在175以上的 人数
select c.cno,c.cname,count(s.sno) as '人数' from class c left join student s on s.cno = c.cno
and s.high > 175
group by c.cno,c.cname
- 6.统计各管理员的工作量(统计选课审核分别是那些管理员通过)
select a.adno,a.adname,count(sc.sno) as '工作量' from admin a
left join sc on substr(sc.adno,4,1) = a.adno
and sc.scstate=1
group by a.adno,a.adname
- 7.找出和陈涛老师 是一个属相的同学名单
select s.name,s.birthday,t.birthday from student s join teacher t
on (date_format(t.birthday,'%Y') - date_format(s.birthday,'%Y')) % 12 =0
and tname='陈涛'
- 8.统计各类别课程的学生人数
select substr(cdesc,1,instr(cdesc,'课程')-1) as '课程名称',count(s.sno) as '人数'
from course c left join sc on c.cno=sc.cno
left join student s on s.sno=sc.sno
group by substr(cdesc,1,instr(cdesc,'课程')-1)
- 8.1统计各类别有多少门课
select substr(cdesc,1,6),count(*) from course
group by substr(cdesc,1,6)
- 字符函数补充
查找函数select instr('abc','a') 后面在前面出现的位置; select locate('a','abc')前面在后面出现的位置;
新题
- 统计各门课的男女人数,显示出课程名称
select c.cno,t.sex,c.cname,count(sc.sno) from (select distinct sex from student) t
left join course c on 1=1
left join sc on sc.cno=c.cno
group by t.sex,c.cno,c.cname
- 找出高于平均选课人数的课程名单
select * from
(select c.cname,count(c.sno) as 'countnumber' from sc join course c on sc.cno=c.cno
group by c.cname ) ce
join
(select avg(cou) as 'avgnumber' from (
select cno,count(sno) as 'cou' from sc
group by cno) s) k on ce.countnumber > k.avgnumber
- 找出选择了数据库类科目的学生名单
SELECT c.cdesc,s.name FROM course c JOIN sc
ON c.cno = sc.cno
JOIN student s
ON sc.sno=s.sno
WHERE c.cdesc LIKE '%数据库%'
- 统计各班选择电子商务课程的学生人数
select c.cno,c.cname,count(sc.cno) from class c left join student s on c.cno=s.cno
left join sc on sc.sno = s.sno
left join course co on co.cno = sc.cno
and co.cname='电商概论'
group by c.cno,c.cname
- 统计各班年龄在27岁以上的人数
select c.cno,c.cname,count(sno) from class c
left join student s
on c.cno=s.cno and floor(timestampdiff(DAY,s.birthday,now())/365) >27
group by c.cno,c.cname
- 统计各位教师的选课人数
select t.tname,count(sc.scno) from teacher t left join sc on t.tno=sc.tno
group by t.tname
- 统计各类别技能掌握的人数
select s.descript,count(e.eid) as '人数' from skill s
left join es on s.sid=es.sid
left join employee e on es.eid = e.eid
group by s.descript
子查询
- 使用内部查询的结果作为外部查询的条件。
- 普通子查询,返回值是一个值或者一列值
- 特殊子查询 all any some
- 存在子查询 exists
- 相关子查询
- 相关存在子查询
- 查询选择了数据库原理 课程的学生名单
连接查询:
三张表连接,如果通篇都没有where子句,on的非主外键 关联的条件不会对
外连接的结果产生干扰,但是会产生额外的组合:
select s.sno,s.name,c.cname
from student s left join sc on s.sno = sc.sno
left join course c on c.cno = sc.cno
and cname = '数据库原理';
三张表连接,一旦有where子句,肯定是内连接的结果:
select s.sno,s.name,c.cname
from student s join sc on s.sno = sc.sno
join course c on c.cno = sc.cno
where cname = '数据库原理';
三张表,先两张表组合,组合后的结果再和第三张表组合,筛选后再进行外连接
的结果:
select s.sno,s.name,t.cname from student s left join
(select cname,sc.sno from sc join
course c on sc.cno = c.cno and cname ='数据库原理') t
on s.sno = t.sno;
子查询:
结果中的字段来自一张表---子查询,来自多张表---连接;
select sno,name from student
where sno in(
select sno from sc
where cno=(
select cno from course where cname='数据库原理')
)
- 找出和陈涛老师同属相的学生名单
子查询:确定表的内外,结果字段所在表在外---
SELECT s.name,s.`birthday` FROM student s
WHERE ((
SELECT DATE_FORMAT(t.birthday,'%Y') FROM teacher t WHERE tname='陈涛')
- DATE_FORMAT(s.birthday,'%Y')) % 12 =0;
2:select * from student s
where (substr(birthday,1,4) -
(select substr(birthday,1,4) from teacher
where tname='陈涛')) % 12 =0
- 找出090102班中比090101班所有同学都高的学生的信息
1:select name,high from student
where cno = '090102' and high >=
(select max(high) from student where cno = '090101')
2:大于any就是大于任意一个,大于all就是大于所有
select name,high from student
where cno = '090101' and high >any
(select high from student where cno = '090201')
- 如果条件查询能够查到任意的返回数据,则外部查询执行
select * from student
where exists (select * from teacher where tno='0009')
普通子查询的执行顺序是,先执行内部查询将内部查询变成一个结果,再和外部查询组合执行;相关子查询,是将
外部查询的数据,一行一行的送入内部查询组合执行,如果内部查询成立则外部查询的那一行数据保留。找出该班学生身高在175以上的人数在2人以上的班级的全体学生的名单
先找出身高175以上人数2人以上的班级
普通子查询解法:
select * from student
where cno in(
select cno from student
where high >=175
group by cno
having count(sno) >=2)
相关子查询解法:
select * from student s1
where exists(
select cno from student s2
where high >=175 and s1.cno = s2.cno
group by cno
having count(sno) >=2)
- 找出高于自己班平均分的学生名单(结果既包含个体的属性,又包含了分组的属性)
select * from
(select name,avgscore,cno from student s1
where exists(
select * from student s3
where(
s1.avgscore >= (select avg(avgscore) from student s2
where s2.cno = s1.cno))
) )t1 join
(select cno,round(avg(avgscore),2) as '班级平均分',count(*) from student
group by cno) t2
on t1.cno = t2.cno
- 找出每个班最高的同学的身高和姓名还要显示班级号
连接查询:
select t.cno,t.maxhigh,s.name from (select cno,max(high) as maxhigh from student group by cno ) t
join student s on t.cno = s.cno and t.maxhigh = s.high
相关子查询:
解题思路:
·显示每个班最高身高的同学的班级号和姓名和身高
·判断每个同学是不是该班最高的,如果是留下,如果不是离开
·找出你们班最高的身高,判断你是否和最高的身高相等
select * from student s1
where exists(
select * from student s3
where s1.high =(
select max(high) from student s2
where s1.cno = s2.cno )
)
- 低于各自班平均身高的信息
select * from student s1
where exists (
select * from student s3
where s1.high<(
select floor(avg(high)) from student s2
where s2.cno = s1.cno
)
)
- 找出可以自驾游的部门
- 找出可以出国自由行的部门的员工名单
相关子查询总结
- 当结果需要同时显示分组的聚合属性(max sum min avg count)和个体属性时候
分别将分组语句的记过和个体查询的结果,以新表重新连接在一起 - 往往这种 分组和 个体属性同时出现,使用相关子查询更为方便。
- 每一条外部查询的数据 作为内部查询的条件和内部查询组合执行,如果执行的结果有数据,则外部查询
这条数据保留,否则 舍弃。 - 如:高于班级平均分的同学留下,找出你自己班的平均分(每个人自己找),判断高于自己班平均分就留下,
低于就离开。 - 完成相关子查询:正常编写内外查询,内外查询之后,使用exists关联,在内部查询中加上外部查询的关联字段,
例如 内部查询一次只找一个班的最值,外部查询来告知哪些值符合条件