联表查询
- join on 连接查询
假设创建以下几个表,
- student表
- result成绩表
练习示例:查询参加了考试的同学(学号,姓名,科目编号,分数)
分析:先分析查询的字段来自哪些表(连接查询),确定使用哪种连接查询(7种)
这张图最后两张在mysql中不支持full outer join
全连接(显示全部数据)
UNION :有去重的功能。
SELECT * FROM tableaA A LEFT JOIN tableB B ON A.id=B.Id UNION
SELECT * FROM tableA A RIGHT JOIN tableB B ON A.id=B. Id;
显示两表的独有的数据
SELECT * FROM tableA A LEFT JOIN tableB B ON A.id=B.Id WHERE A.Id IS NULL UNION
SELECT * FROM tableA A RIGHT JOIN tableB B ON A.id=B.Id WHERE B.id IS NULL
确定交叉点,即这两个表中的哪些数据是相同的,再判断条件,即学生表中的学号=成绩表的学号
select s.studentno,studentname,subjectno,studentresult from
student as s inner join
result as r
on s.studentno=r.studentno
结果:
- inner join:表示如果两表中至少有一个匹配,就返回数据
- left join:会从左表中返回所有的值,即使右表中没有匹配
- right join:会从右表中返回所有的值,即使左表中没有匹配
联表根据条件查询:where(等值查询)
- 查询缺考的同学:
select s.studentno,studentname,subjectno,studentresult from
student as s left join
result as r
on s.studentno=r.studentno
where r.studentresult is null
联表查询三张表
subject表:
- 查询了参加考试的同学信息,学号,学生姓名,科目名,分数
--分析查询的字段来自哪些表,student,result,subject(连接查询),再确定使用哪种连接,这里先查前两张表,有考试,则用右连接result表,确定交叉点,先确定是通过学生studentno相同查询
select s.studentno,studentname,subjectno,studentresult from
student as s right join
result as r
on s.studentno=r.studentno
结果是前两张表的联表查询
因为要与第三张表subject联表,则再进行联表查询,确定使用哪种连接,这里可以用内连接,再确定交叉点,通过科目subjectno相同进行查询
select s.studentno,studentname,subjectname,studentresult from
student as s right join
result as r
on s.studentno=r.studentno
inner join `subject` as sub
on r.subjectno=sub.subjectno
最后结果:
自连接
它是自己的表和自己的表连接,即一张表拆分为两张一样的表
示例:
假设拆成一张表为父表
categoryid | categoryname |
---|---|
2 | 信息技术 |
3 | 软件开发 |
5 | 美术设计 |
再拆成一张子表
pid | categoryid | categoryname |
---|---|---|
3 | 4 | 数据库 |
2 | 8 | 办公信息 |
3 | 6 | web开发 |
5 | 7 | ps技术 |
查询父表对应的子表关系
父表 | 子表 |
---|---|
信息技术 | 办公信息 |
软件开发 | 数据库 |
软件开发 | web开发 |
美术技术 | ps技术 |
select a.categoryname as 父表 ,b.categoryname as 子表 from
category as a,category as b
where a.categoryid=b.pid
结果:
排序
- order by 字段 desc :表示降序
- order by 字段 asc :表示升序
--降序
select s.studentno,studentname,subjectname,studentresult from
student as s right join
result as r
on s.studentno=r.studentno
inner join `subject` as sub
on r.subjectno=sub.subjectno
order by studentresult desc
结果:
--升序
select s.studentno,studentname,subjectname,studentresult from
student as s right join
result as r
on s.studentno=r.studentno
inner join `subject` as sub
on r.subjectno=sub.subjectno
order by studentresult asc
结果:
分页查询
limit 初始值,分页大小
示例:
select s.studentno,studentname,subjectname,studentresult from
student as s right join
result as r
on s.studentno=r.studentno
inner join `subject` as sub
on r.subjectno=sub.subjectno
order by studentresult asc
limit 0,5
结果:
拓展:
第一页-----limit 0,5-------(1-1)*5---------第一页查询5条数据
第二页-----imit 5,5 -------(2-1)*5---------第二页查询5条数据
第n页------ … -------------(n-1)*pagesize,pagesize
(n-1)*pagesize -----------初始值
pagesize-------------------页面大小
总页面----------------------数据总数/页面大小
n-----------------------------当前页
子查询(嵌套查询)
在where语句中嵌套一个子查询语句,程序先运行在嵌套在最内层的语句,再运行外层
示例:
-- 查询数据库结构-1的所有考试结果(学号,科目编号,成绩),降序排列
-- 方式一:使用连接查询
select studentno,r.subjectno,studentresult from result as r
inner join subject as sub
on sub.subjectno=r.subjectno
where sub.subjectname='数据库结构-1'
order by studentresult desc
-- 方式二,使用子查询(由里到外,先查取subject中数据库结构-1的科目编号,再根据条件查询)
select studentno,r.subjectno,studentresult from result as r
where subjectno=(
select subjectno from subject where subjectname='数据库结构-1'
)
order by studentresult desc
- 查询编号为高等数学-2,分数不小于80分的学生的学号和姓名
-- 方式一(连接查询)
select s.studentno,studentname,r.studentresult from student s
inner join result r
on s.studentno=r.studentno
inner join `subject` sub
on sub.subjectno=r.subjectno
where subjectname='高等数学-2'
and studentresult>=80
-- 方式二(子查询)
select s.studentno,studentname,r.studentresult from student s
inner join result r
on s.studentno=r.studentno
where studentresult>=80 and r.subjectno=(
select subjectno from subject as sub
where subjectname='高等数学-2'
)
-- 方式三(多个嵌套查询,先查分数大于80分的 学生 ,再查询科目是高等数学-2)
select s.studentno,studentname from student s
where s.studentno in(
select studentno from result where studentresult>=80
and subjectno =(select subjectno from subject where subjectname='高等数学-2'
)
)
分组和过滤查询
-- 查询不同课程的平均分,最高分,最低分,平均分大于80
select subjectname,avg(studentresult),max(studentresult),min(studentresult) from result as r
inner join subject as sub
on r.subjectno=sub.subjectno
-- 通过不同的课程来分组
group by subjectname
-- 通过分组后来筛选平均分大于80分
having avg(studentresult)>=80