一,子查询定义:

子查询就是嵌套在主查询中的查询。

子查询可以嵌套在主查询中所有位置,包括SELECT、FROM、WHERE、GROUP BY、HAVING、ORDER BY。

但并不是每个位置嵌套子查询都是有意义并实用的。

二,子查询的返回:

一个子查询会返回一个标量(单一值)、一个行、一个列或一个表(一行或多行及一列或多列)。这些子查询被称为标量、列、行和表子查询

1,单行单列,聚合(标量):

返回的结果集为单个的子查询,叫做单行子查询。单行比较符有: =、 >、>=、<、<=、!=

2,单行多列:

SELECT * FROM t1 WHERE (1,2) = (SELECT column1, column2 FROM t2);
SELECT * FROM t1 WHERE ROW(1,2) = (SELECT column1, column2 FROM t2);

如果在表t2的一个行中,column1=1并且column2=2,则查询结果均为TRUE。

表达式(1,2)和ROW(1,2)有时被称为行构造符。两者是等同的,在其它的语境中,也是合法的。例如,以下两个语句在语义上是等同的(但是目前只有第二个语句可以被优化):

SELECT * FROM t1 WHERE (column1,column2) = (1,1);
SELECT * FROM t1 WHERE column1 = 1 AND column2 = 1;

3,多行单列与多行多列:

返回的结果集为多个的子查询,为多行子查询,多行子比较符有 IN(等于列中任意一个)、ANY(和子查询返回的某个值比较),ALL(和子查询返回的所有值比较)

NOT IN是<> ALL的别名

IN是=ANY的别名

三,EXISTS和NOT EXISTS

该语法可以理解为:将主查询的数据,放到子查询中做条件验证,根据验证结果(TRUE 或 FALSE)来决定主查询的数据结果是否得以保留。请参考

https://blog.csdn.net/qq_27571221/article/details/53090467

四,关联子查询

相关联的子查询是一个包含对表的引用的子查询。该表也显示在外部查询中。例如:

SELECT * FROM t1 WHERE column1 = ANY (SELECT column1 FROM t2 WHERE t2.column2 = t1.column2);

注意,即使子查询的FROM子句不提及表t1,该子查询也会包含一个对t1中一列的引用。所以,MySQL看上去位于子查询的外部,并在外部查询中查找t1。

假设表t1包含一行,在此行中column1=5并且column2=6;同时,表t2包含一行,在此行中column1=5并且column2=7。简单的表达式... WHERE column1 = ANY (SELECT column1 FROM t2)会为TRUE。但是在本例中,在子查询中的WHERE子句为FALSE(因为(5,6)不等于(5,7)),所以子查询总体上为FALSE。

范围划分规则:MySQL从内到外进行评估。例如:

SELECT column1 FROM t1 AS x
WHERE x.column1 = (SELECT column1 FROM t2 AS x
WHERE x.column1 = (SELECT column1 FROM t3
WHERE x.column2 = t3.column1));

在本语句中,x.column2必须是表t2中的列,因为SELECT column1 FROM t2 AS x ...对t2进行了重命名。它不是表t1中的列,因为SELECT column1 FROM t1 ...是一个更靠外的外部查询。

对于HAVING或ORDER BY子句中的子查询,MySQL也会在外部选择清单中寻找列名称。

对于特定的情况,相关联的子查询被优化。例如:

val IN (SELECT key_val FROM tbl_name WHERE correlated_condition)

否则,这些子查询效率不高,可能速度会慢。把查询作为联合进行改写可能会改进效率。

相关联的子查询不能从外部查询中引用总计函数的结果。

五,在FROM中嵌套

from下的子查询 相当于返回一张表,并且要强制取名

在SELECT语句的FROM子句中,子查询是合法的。实际的语法是:

SELECT ... FROM (subquery) [AS] name ...

[AS] name子句是强制性的,因为FROM子句中的每个表必须有一个名称。在子查询选择列表中的任何列都必须有唯一的名称。您可以在本手册中的其它地方找到对本语法的说明。在该处,所用的词语是“导出表”。

为了进行详细说明,假设您有如下一个表:

CREATE TABLE t1 (s1 INT, s2 CHAR(5), s3 FLOAT);

下面使用了示例表,解释了在FROM子句中如何使用子查询:

INSERT INTO t1 VALUES (1,'1',1.0);
INSERT INTO t1 VALUES (2,'2',2.0);
SELECT sb1,sb2,sb3
FROM (SELECT s1 AS sb1, s2 AS sb2, s3*2 AS sb3 FROM t1) AS sb
WHERE sb1 > 1;
//结果:2, '2', 4.0。

下面是另一个例子:假设您想了解一个分类后的表的一组和的平均值。采用如下操作:

SELECT AVG(SUM(column1)) FROM t1 GROUP BY column1;

不过,本查询提供所需的信息:

SELECT AVG(sum_column1)
FROM (SELECT SUM(column1) AS sum_column1
FROM t1 GROUP BY column1) AS t1;

注意,在子查询中使用的列名称(sum_column1)被整理到外部查询中。

FROM子句中的子查询可以返回标量、列、行或表。FROM子句中的子查询不能为有关联的子查询。

即使对EXPLAIN语句(即建立临时导出表),FROM子句中的子查询也会被执行。这是因为在优化过程中,上一级的查询需要有关所有表的信息。

六,在SELECT中嵌套:

select中的子查询如果是相关子查询,貌似可以和join关联查询转换

现有表两张:一张学生表、一张班表。id相关联

学生信息和班级名称位于不同的表中,要在同一张表中查出学生的学号、姓名、班级名称:

SELECT s.student_id,s.student_name,(SELECT class_name FROM t_class c WHERE c.class_id=s.class_id) FROM t_student s GROUP BY s.student_id; 

首先这条SQL语句用到了别名,写法为在FORM的表名后加上某个字符比如FROM t_student s,这样在之后调用t_student的某一列时就可以用s.student_id来强调此列来源于对应别名的那张表。(这是一个相关子查询)

别名在子查询及联接查询中的应用有着很好效果,当两张表有相同列名或者为了加强可读性,给表加上不同的别名,就能很好的区分哪些列属于哪张表。

还有种情况就是在子查询或联接查询时,主查询及子查询均为对同一张表进行操作,为主、子查询中的表加上不同的别名能够很好的区分哪些列的操作是在主查询中进行的,哪些列的操作是在子查询中进行的,下文会有实例说明。

接下来回到上面的SQL语句中,可以看出本条子查询的嵌套是在SELECT位置(括号括起来的部分),它与学号、学生姓名以逗号分隔开并列在SELECT位置,也就是说它是我们想要查出的一列,

子查询中查出的是,班级表中的班级id与学生表中的班级id相同的行,注意 WHERE c.class_id=s.class_id 这里就是别名用法的一个很好的体现,区分开了两张表中同样列名的列。

七,在WHERE中嵌套:

现要查出C语言成绩最高的学生的信息:

SELECT * FROM t_student WHERE student_subject='C语言' AND student_score>= 
ALL (SELECT student_score FROM t_student WHERE student_subject='C语言') ;

这里出现了一个ALL,其为子查询运算符

分类:

–ALL运算符

  和子查询的结果逐一比较,必须全部满足时表达式的值才为真。

–ANY运算符

  和子查询的结果逐一比较,其中一条记录满足条件则表达式的值就为真。

–EXISTS/NOT EXISTS运算符

  EXISTS判断子查询是否存在数据,如果存在则表达式为真,反之为假。NOT EXISTS相反。

在子查询或相关查询中,要求出某个列的最大值,通常都是用ALL来比较,大意为比其他行都要大的值即为最大值。

要查出C语言成绩比李四高的学生的信息:

SELECT * FROM t_student WHERE student_subject='C语言' AND student_score > 
(SELECT student_score FROM t_student WHERE student_name='李四' AND student_subject='C语言');

通过上面两例,应该可以明白子查询在WHERE中嵌套的作用。通过子查询中返回的列值来作为比较对象,在WHERE中运用不同的比较运算符来对其进行比较,从而得到结果。

现在我们回到最开始的问题,怎么查出每门课最高成绩的学生的信息:(这个也是相关子查询)

SELECT * FROM t_student s1 WHERE s1.student_score >= 
ALL(SELECT s2.student_score FROM t_student s2 WHERE s1.`student_subject`=s2.student_subject);

这里就是上文提到的别名的第二种用法,主、子查询对同一张表操作,区分开位于内外表中相同的列名。

八,子查询的分类:

–相关子查询

  执行依赖于外部查询的数据。(就是table1在该select外面,而select里面table1.xx=table2.xx)

  外部查询返回  一行 ,子查询就执行一次。(对于该select,里面的子select会重复很多次执行)

–非相关子查询

  独立于外部查询的子查询。

  子查询总共执行一次,执行完毕后后将值传递给外部查询。

上文提到的例子中,第一个例子求学生对应班级名的即为相关子查询,其中WHERE c.class_id=s.class_id 即为相关条件。其他的例子均只对一张表进行操作,为非相关子查询。

需要注意的是相关子查询主查询执行一回,子查询就执行一回,十分耗费时间,尤其是当数据多的时候。

SQL语句:子查询的更多相关文章

  1. SQL Fundamentals: 子查询 || 分析函数(PARTITION BY,ORDER BY, WINDOWING)

    SQL Fundamentals || Oracle SQL语言 子查询(基础) 1.认识子查询 2.WHERE子句中使用子查询 3.在HAVING子句中使用子查询 4.在FROM子句中使用子查询 5 ...

  2. SQL Fundamentals: 子查询 || WHERE,HAVING,FROM,SELECT子句中使用子查询,WITH子句

    SQL Fundamentals || Oracle SQL语言 子查询(基础) 1.认识子查询 2.WHERE子句中使用子查询 3.在HAVING子句中使用子查询 4.在FROM子句中使用子查询 5 ...

  3. C#构造方法(函数) C#方法重载 C#字段和属性 MUI实现上拉加载和下拉刷新 SVN常用功能介绍(二) SVN常用功能介绍(一) ASP.NET常用内置对象之——Server sql server——子查询 C#接口 字符串的本质 AJAX原生JavaScript写法

    C#构造方法(函数)   一.概括 1.通常创建一个对象的方法如图: 通过  Student tom = new Student(); 创建tom对象,这种创建实例的形式被称为构造方法. 简述:用来初 ...

  4. MySQL的EXPLAIN命令用于SQL语句的查询执行计划

    MySQL的EXPLAIN命令用于SQL语句的查询执行计划(QEP).这条命令的输出结果能够让我们了解MySQL 优化器是如何执行SQL 语句的.这条命令并没有提供任何调整建议,但它能够提供重要的信息 ...

  5. mysql 常用 sql 语句 - 快速查询

    Mysql 常用 sql 语句 - 快速查询 1.mysql 基础 1.1 mysql 交互         1.1.1 mysql 连接             mysql.exe -hPup    ...

  6. SQL语句在查询分析器中可以执行,代码中不能执行

    问题:SQL语句在查询分析器中可以执行,代码中不能执行 解答:sql中包含数据库的关键字,将关键字用[]括起来,可以解决. 后记:建数据库的时候尽量避免使用关键字. 例子: sql.Format(&q ...

  7. 如何在 Linux 上用 SQL 语句来查询 Apache 日志

    Linux 有一个显著的特点,在正常情况下,你可以通过日志分析系统日志来了解你的系统中发生了什么,或正在发生什么.的确,系统日志是系统管理员在解决系统和应用问题时最需要的第一手资源.我们将在这篇文章中 ...

  8. 在Hibernate中使用HibernateTemplate来进行包含sql语句的查询

    /**     * 使用sql语句进行查询操作     * @param sql     * @return     */    public List queryWithSql(final Stri ...

  9. Sql语句之查询所有学生所有科目分数及总分

    昨天练Sql语句,数据库建了四个表分别是,学生表,课程表,成绩表以及教师表(教师表不在讨论范围),突然想到以前高中时代老师手上的那张成绩表,然后我就寻思着能不能用Sql语句把表打印出来,以下是我的思考 ...

  10. Python与开源GIS:在OGR中使用SQL语句进行查询

    摘要: 属性选择与空间选择都可以看作是OGR内置的选择功能,这两种功能可以解决大部分实际中的问题.但是也有这种时候,就是进行查询时的条件比较复杂.针对这种情况,OGR也提供了更加灵活的解决方案:支持使 ...

随机推荐

  1. element vue 表格编辑

    https://xuliangzhan.github.io/vue-element-extends/#/editable/click1

  2. codeforces16B

    Burglar and Matches CodeForces - 16B A burglar got into a matches warehouse and wants to steal as ma ...

  3. dataframe常用处理

    获取列名:data.columns.values.tolist() 复制列: out['serial_number'] = out['2']这样就是新增了一列,复制了‘2’这一列,然后再del out ...

  4. 京东商品及评论爬虫(selenium)

    代码查看https://gitee.com/MarkPolaris/reptile/tree/master/jd 中的gly和demo03

  5. [SDOI2017]遗忘的集合

    [SDOI2017]遗忘的集合 综合了很多套路的题 一看就是完全背包 生成函数! 转化为连乘积形式 Pi....=F 求Ln! 降次才可以解方程 发现方程是: f[i]=∑t|i : bool(t)* ...

  6. Java反射-修改字段值, 反射修改static final修饰的字段

    反射修改字段 咱们从最简单的例子到难, 一步一步深入. 使用反射修改一个private修饰符的变量name 咱们回到主题, 先用反射来实现一个最基础的功能吧. 其中待获取的name如下: public ...

  7. python 高级部分

    伴随视频可以观看 因为Python的线程虽然是真正的线程,但解释器执行代码时,有一个GIL锁:Global Interpreter Lock,任何Python线程执行前,必须先获得GIL锁,然后,每执 ...

  8. 定时调度系列之Quartz.Net详解

    一. 背景 我们在日常开发中,可能你会遇到这样的需求:"每个月的3号给用户发信息,提醒用户XXX "."每天的0点需要统计前一天的考勤记录"."每个月 ...

  9. [BZOJ 4152][AMPPZ 2014]The Captain

    这道题对费用的规定是min(|x1-x2|,|y1-y2|).如果暴力枚举所有的点复杂度O(n²),n <= 200000,显然爆炸.于是我们要考虑加“有效边”,一个显然的事实是对于两个点,如果 ...

  10. Basic 001 Bob

    Instructions Bob is a lackadaisical teenager. In conversation, his responses are very limited.Bob an ...