相关子查询与非相关子查询的理解
子查询基本概念:
1.如果一个select语句能够返回单个值或一列值,且该select语句嵌套在另一个SQL语句例如(insert、delete、update、select)中,那么该select语句称为子查询,也叫内层查询,包含子查询的语句称为主查询。
2.通常情况下,子查询写在小括号内,子查询一般用在主查询的where子句或having子句中与比较运算符或逻辑运算符一起构成where或having筛选条件。
3.子查询分为相关子查询与非相关子查询
非相关子查询:
子查询select语句的结果集的筛选使用自己定义的数据源,不引用主查询的数据源,在整个SQL语句执行过程中只执行一次。
通俗理解:子查询select语句自己 定义筛选结果集的数据源,即where或having 条件的数据源,其整条SQL语句完全可以脱离主查询而单独执行,相当于一条正常的selet语句,该语句执行完后将执行结果返回到主查询的where/having语句中,作为条件为主查询服务。
具体实现:
数据源choose表信息:
执行
select student.*, course_name,score from choose join student join course
on choose.student_no = student.student_no and choose.course_no =course.course_no
即可得到下面的信息:
例如:检索成绩比学生‘张三’平均分高的所有学生即课程的信息
select student . *, course_name,score from choose join student join course
on choose.student_no = student.student_no and choose.course_no =course.course_no
where score >
(select avg(score) from choose join student on choose.student_no =student.student_no where student_name =‘张三’)
实现截图:
检索学生‘张三’成绩比本人平均分高的个人及课程信息
select student.* ,course_name ,score from choose **
join** student on choose.student_no =student.student_no join course on choose.course_no = course.course_no
where score >
(select avg(score) from choose join student on choose.student_no =student.student_no where student_name = ‘张三’ ) having student_name =‘张三’
实现截图:
从上述可以很清晰的看出,非相关子查询的语法格式与主查询的语法格式几乎相同,俩者之间可以说是不存在任何关联,而该子查询存在的意义,仅仅是作为一个结果集返回到主查询where子句中,充当一个条件而已。
相关子查询:
子查询的结果集的筛选条件依赖于主查询的数据源,主查询每执行一次(检索一行记录),子查询则执行一次(检索所有行记录),且子查询的结果集作为主查询的where/having子句来筛选符合条件的最终结果集。
通俗理解:子查询的where/having的条件来自主查询的数据源表,每次主查询检索一行记录时,子查询都要通过where/having子句来筛选结果集作为 主查询where/having子句的条件,来完成主查询每一行记录的筛选,每次筛选完,主查询进入下一行的筛选,子查询与之同步,最终将符合条件的结果集返回到客户机上。
具体实现:
检索学生‘张三’成绩比本人平均分高的个人及课程信息
select student.*, course_name,score from choose join student join course
on choose.student_no = student.student_no and choose.course_no =course.course_no
where score >
(select avg(score) from choose where student.student_no = choose.student_no and student_name =‘张三’ )
实现截图:
检索课程名为‘MySQL数据库得分最高的个人信息及课程信息
select student.*, course_name,score from choose join student join course
on choose.student_no = student.student_no and choose.course_no =course.course_no
where score in
(select max(score) from choose where course_name =‘MySQL数据库’)
实现截图:
从上述测试中可以看出,相关子查询与主查询呈现互为依赖的关系,且依赖程度大于非相关子查询,子查询每次需要调用主查询的数据源作为该where语句的执行条件,才能完成select语句的执行,而主查询也必须要等子查询返回结果集作为主查询where子句的筛选条件,才能完成对整个SQL语句的执行。
相关子查询的执行过程:
1.由于主查询where/having子句的限制,主查询无法一次性完成对数据源表中所有记录的检索,因而主查询每检索一行记录时都要经过where/having子句的筛选,而子查询的结果集又作为主查询的where子句必要的筛选条件,因此子查询也需要完成对结果集的筛选,其子查询where条件又来自主查询的数据源表,因此需要主查询每次检索一行记录后,子查询才能根据主查询的执行情况,筛选符合条件的结果集作为主查询的where子句的条件,以至最终完成对SQL语句的执行。
3.子查询的执行过程:
以检索学生‘张三’成绩比本人平均分高的个人及课程信息为例
1)主查询先查询第一条记录即学号为’2020001’的学生及课程信息
2)子查询根据主查询提供学号为’2020001’记录行,根据where子句在choose中进行筛选
3)筛选结束后,则结果集返回到主查询where子句中,进行二次筛选
5)主查询where子句筛选结束后,主查询再进入第二行记录的检索
6)依次往复的筛选,直至检索结束,将最终结果集返回到客户机上
注:子查询的真正数据源其实是来自choose表,即自身定义用来查询score字段的表,而借用主查询student表只是仅仅为了进行结果集的筛选,千万不要搞混!!!!!!
按照上诉所说,如果我们想要用相关子查询来检索学生在各科上的最低分的课程信息及学生信息,该如何去做?
检索学生哪门科目得分最低,并查询该科的课程名以及学生信息(使用相关子查询实现)
select student.* ,course_name ,score from choose
join student on choose.student_no =student.student_no join course on choose.course_no = course.course_no
where score in
(select min(score) from choose where choose.student_no = student.student_no )
实现效果:
**讲到这里,相信大家基本上对相关子查询与非相关子查询的概念有了初步理解,以上内容都是均来自我的多测试与总结,如有不对的地方,可以评论交流,毕竟大家都只是一个初学者而已。
**
知识补充:
where子句与having子句的用途与区别:
1)where/having子句可以对select查询的字段进行条件设置
select score from choose where score>40
select score from choose having score >40
2)where语句支持非select查询字段的条件设置,但该字段必须来自select检索的表
select score from choose where student_no = ‘2020001’
3)having子句支持聚合函数字段的条件设置以及group by 分组结果集等的二次筛选
select avg(score) from choose having avg(score) >60
select class_name , student_no,student_name ,student_sex from student
join classes on classes.class_no =student.class_no
where student_name = ‘张三’
group by class_name
having student_sex =‘女’