SQL子查询总结:相关子查询与非相关子查询有什么区别

知乎 · · 184 次点击 · · 开始浏览    
如果一个select语句能够返回单个值或者一列值,且该select语句嵌套在另一个SQL语句(例如select语句、insert语句、update语句或者delete语句)中,那么该select语句成为“子查询”(也叫内层查询),包含子查询的SQL语句称为“主查询”(也叫外层查询)。为了标记子查询与主查询之间的关系,通常将子查询写在小括号内。子查询一般用在主查询的where子句或having子句中,与比较运算符或者逻辑运算符一起构成where筛选条件或having筛选条件。子查询分为“相关子查询”(Dependent Subquery)与“非相关子查询”。

非相关子查询

如果子查询返回单个值,则可以讲一个表达式的值与子查询的结果进行比较。 例如,检索成绩比学生张三平均分高的所有学生及课程的信息, 可以使用下面的SQL语句, 执行结果如下图。

mysql> select class_name, student.student_no, student_name, course_name, score
    -> from classes join student on student.class_no = classes.class_no
    -> join choose on choose.student_no = student.student_no
    -> join course on choose.course_no = course.course_no
    -> where score > (
    -> select avg(score)
    -> from student, choose
    -> where student.student_no = choose.student_no and student_name = '张三'
    -> );
非相关子查询

说明

该示例中的子查询是一个单独的select语句,可以不依赖主查询单独运行。这种不依靠主查询,能够独立运行的子查询称为**“非相关子查询”**。

执行过程

  1. 执行子查询,其结果不被显示,而是传递给外部查询,作为外部查询的条件使用。
  2. 执行外部查询,并显示整个结果。

相关子查询

下面的示例演示了相关子查询,代码第七行标记了两条子查询语句之间的区别(其他SQl代码完全相同),执行结果如下图。

mysql> select class_name, student.student_no, student_name, course_name, score
    -> from classes join student on student.class_no = classes.class_no
    -> join choose on choose.student_no = student.student_no
    -> join course on choose.course_no = course.course_no
    -> where score > (
    -> select avg(score)
    -> from choose
    -> where student.student_no = choose.student_no and student_name = '张三'
    -> );
相关子查询

说明

从执行结果可以看到,子查询可以仅仅使用自己定义的数据源,也可以“直接引用”主查询中的数据源,但两者意义完全不同。

  1. 如果子查询中仅仅使用了自己定义的数据源, 这种查询是非相关子查询。 非相关子查询是独立于外部查询的子查询, 子查询总共执行一次, 执行完毕后将值传递给主查询。
  2. 如果子查询中使用了主查询的数据源, 这种查询是相关子查询, 此时主查询的执行与相关子查询的执行相互依赖

执行过程

  1. 从外层查询中取出一个元组,将元组相关列的值传递给内层查询。
  2. 执行内层查询,得到子查询操作的值。
  3. 外查询根据子查询返回的结果或结果集得到满足条件的行。
  4. 然后外层查询取出下一个元组重复做步骤1-3,直到外层的元组全部处理完毕。

如何区分

说了这么多,那我们该如何快速区分非相关子查询和相关子查询呢?

最简单的办法的就是直接看子查询本身能否执行。比如执行上面的例子中的子查询:

mysql> select avg(score)
    -> from choose
    -> where student.student_no = choose.student_no and student_name = '张三';
子查询

会报错:1054 - Unknown column 'student.student_no' in 'where clause' 这样的查询语句构成的子查询便为相关子查询

本文来自:知乎

感谢作者:知乎

查看原文:SQL子查询总结:相关子查询与非相关子查询有什么区别

184 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传