目录
Day 8~9
一、查询语句子句
1、查询语句子句的优先级
- select --5
- from --1
- where --2
- group by --3
- having --4
- order by --6
1、select
- select后可以跟一个/多个属性
- 属性间隔符是英文逗号","
- 属性后面可以加别名,中间空格隔开
- 用distinct可以使属性去重
2、from
- 生成实例
- 生成笛卡尔乘积
- for循环
3、where
- 可以比大小:分别是大于、大于等于、小于、小于等于、等于、不等于(符号表示为> | >= | < | <= | = | != | <> ,最后两张都是不等于)
- 数值可以比大小,字符串也可以比大小
- 条件可以是多个,条件之间的关系有三种:与或非(and or not)
- 条件之间也有优先级: () > not > and > or ,括号优先级最高
- xx between ’ y’ and ’ z’ 等价于 xx>‘y’ and xx<‘z’ 一般用在连续的数值关系上
- 如果数值之间间断的,可以用 xx in (x,y,z) 表示在x和y和z中
- 模糊查询 like,%表示多个任意字母,_表示任意一个字母
- 对不存在的数据进行对比,xx is null,表示查询 xx 属性不存在的数据,is not null (not is null 也行)表示查询存在的
4、group by
- group by 首先根据分组特征创建出多个分组,然后通过for循环遍历每个小组,将其交给后续执行的子句
- 分组语句只能查询分组特征,分组的目的在于统计,所有的统计(聚合/聚集)函数一共有5个,分别是最大、最小、平均、总和以及组内成员数目(max、min、avg、sum、count)
- 支持多属性分组
- 当统计数目时,若为空则不纳入统计
- 1、找出各个班级中的人数总和
select sclass,count(*)
from student
group by sclass
- 2、请用查询语句找出各个班级的同学分别来自多少个不同的地区
select sclass 班级,count(distinct snativeplace) 不同的地区
from student
group by sclass
- 3、找出各个班级的男生分别有多少个不同的名族
select sclass,count(distinct snative)
from student
where ssex='男'
group by sclass
- 没有group by语句实际上是默认分组,默认分组不可以查询任何显示属性
- 先分组,再统计,参考查询语句子句优先级,所以where语句中不能出现统计函数,能够出现统计函数的子句有select、having、order by。
5、having
- having和where一样是条件过滤语句
where语句过滤的是每次from循环交给where的一条记录
having语句过滤的是每次group by循环交给having的一个小组 - 1、请查询出每个学生(sid)和其均分、最低分和最高分
select sid,avg(cmark),min(cmark),max(cmark)
from mark
group by sid
- 2、找出没有不及格成绩的学生(sid)=哪些学生最低分大于等于60
select sid
from mark
group by sid
having min(cmark)>=60
- 3、哪些地区的男生人数大于2
select snativeplace,count(*)
from student
where ssex='男'
group by snativeplace
having count(sid)>2
select snativeplace,count(*)
from student
group by snativeplace,ssex
having ssex='男' and count(sid)>2
6、order by
- 排序特征
- 默认由小到大(升序)排序
- 逆序(降序)排序 desc
- 顺序(升序)排序 asc 可省略
- 根据均分降序排序显示每个学生的sid和平均分
select sid,avg(mark)
from mark
group by sid
order by avg(mark) desc
/*起别名*/
select sid,avg(mark) amk
from mark
group by sid
order by amk desc
- 可以根据多个属性排序
- eg.现根据年龄排序,再根据学号排序,只有一阶排序分不出大小的时候才会用到二阶排序
select *
from student
order by sage desc,sid asc
二、单表查询习题
1、找出张三和李四所在班级
select distinct sclass
from student
where sname in('张三','李四')
2、找出各个地区的男生分别来自多少个不同的民族
select snativeplace,count(distinct snative)
from student
where ssex='男'
group by snativeplace
3、哪些地区男生的平均年龄>20岁
select snativeplace,avg(sage)
from student where ssex='男'
group by snativeplace
having avg(sage)>20
4、由高到低显示各个班级的男生人数,显示班级名称和男生人数
select sclass,count(*) cnt
from student where ssex='男'
group by sclass
order by cnt desc
三、多表查询
1、多表组合
1.1 多表合并
- 多表合并的基本思想是将两张或者两张以上的表格合并为一张表格,然后进行单表查询
- 笛卡尔乘积带来的大部分结果都是没有意义的
- 1、找出张三的2001号课程成绩
select *
from student,mark
where student.sid = mark.sid and sname='张三' and cid=2001
- 2、找出张三数学成绩
select cmark
from student,mark,course
where student.sid=mark.sid and mark.cid=course.cid
and sname='张三' and cname='数学'
- 3、找出各个地区的数学均分
将三表组合
先用where过滤出cname=‘数学’
根据snativeplace进行分组
统计出各个地区的avg(cmark)
select snativeplace,avg(cmark)
from student s,mark m,course c
where cname='数学' and s.sid=m.sid and m.cid=c.cid
group by snativeplace
- 4、找出各个地区的男生各科均分
select snativeplace,avg(cmark)
from student s,mark m,course c
where s.sid=m.sid and m.cid=c.cid
group by snativeplace,c.id,ssex
having ssex='男'
- 5、找出每个学生的平均分,要求显示姓名和均分
将student表和mark组合成单表
将这张单表根据sname进行分组
投影sname和avg(cmark)
select sname,avg(cmark)
from student s,mark m
where s.sid=m.sid
group by s.sid,snam
1.2 多表连接
- 特殊的多表组合场景
查询的特征决定了不同的行中的数据是无法比对的!
比对有三种方式:
1:将一个常量和一个常量进行相比
where 1=0
2:将一个变量和一个常量进行相比
where sage=19
3:将一个变量和一个变量进行比对
必须让这两个变量处于同一行才有比对的可能
- 找出哪些学生的2001号课程成绩比2002号课程成绩高?只要显示这些学生的sid即可
select a.sid
from mark a,mark b
where a.sid=b.sid
and a.cid=2001 and b.cid=2002
and a.cmark>b.cmark
- 10002号学生的哪些课程成绩比10003高?找出课程名称
select cname
from mark a,mark b,course c
where a.cid=b.cid and a.sid=10002 and b.sid=10003
and a.cid=c.cid and a.cmark>b.cmark
- 张三哪些课程成绩李四高?找出课程名称
select cname
from mark a,mark b,student s1,student s2,course c
where a.cid=b.cid and a.sid=s1.sid and b.sid=s2.sid
and s1.sname='张三' and s2.sname='李四'
and a.cid=c.cid and a.cmark>b.cmark
2、子查询
- 子查询又叫代入查询
- 根据代入的语句分为:条件子查询 表格子查询 select子查询 相关子查询
- 找出张三的平均分[条件子查询]
select sid from student where sname='张三'
select avg(cmark) from mark where sid=1002
/*分多次查询的过程中消耗了无谓的延时和cpu*/
select avg(cmark) from mark
where sid=(select sid from student where sname='张三'
)
- 找出年龄最大的学生姓名
--方法一[条件子查询]
step1:找出最大年龄
select max(sage) from student
step2:找学号
select * from student where sage=(step1)
--方法二:将学生根据年龄降序排序,排序后取第一条记录
- 找出年龄最大的女生姓名
step1:找出最大年龄的女生
select max(sage) from student where sage='女'
step2:找姓名
select sname from student where sage=(step1)
- 找出张三的最高分对应的课程名[条件子查询]
--step1:找出张三的sid
select sid from student where sname='张三'
--step2:找最高分
select max(cmark) from mark where sid=(step1)
--step3:找最高分对应的cid
select cid from mark where sid=(step1) and cmark=(step2)
--step4:找cid对应的cname
select cname from course where cid in(step3)
- 找出最高均分[表格子查询 from语句]
step1:select sid,avg(cmark) amk from mark group by sid
step2:select max(amk) from (step1)
- 找出均分最高的男生[表格子查询]
step1:在student表中找出所有男生的sid
select sid from student where ssex='男'
step2:在mark表中根据男生的sid,找出平均分表
select sid,avg(mark) amk from mark where sid in(step1) group by sid
step3:在step2的表中找出最高平均分
select max(amk) from (step2)
step4:在step2的表中找均分等于step3的sid
select sid from (step2) where amk=(step3)
step5:在student表中将sid换成sname
select sname from student where sid in(step4)
3、多表集合运算
四、课后习题
1、找出年龄降序排序的5-8名学生信息
降序
取前8条记录,逆转这8条记录的顺序
取前4条记录,再逆转顺序
select * from (
select * from (
select * from student order by sage desc
) where rownum<=8 order by sage asc
) where rownum<=4 order by sage desc;
2、找出均分由高到低排序中第10-15名学生的姓名和其均分
找出均分降序排列的学生sid和avg(cmark)
取前15条记录,逆转这15条记录的顺序
取前5条记录,再逆转顺序
select sname,amk
from (
select sname,amk
from (
select sid,avg(cmark) amk from mark group by sid order by amk desc
) s1,student where s1.sid=student.sid and rownum<=15 order by amk asc
) s2
where rownum<=5
order by amk desc