前面说了很多MySQL中的查询,比如条件查询、分组聚合查询、连接查询,今天来说一下另外两个非常的重要的查询,MySQL中的子查询和联合查询。
PART01
子查询
子查询也称嵌套查询,是将一个查询语句嵌套在另一个查询语句的WHERE子句或者HAVING短语中,前者被称为内层查询或子查询,后者被称为外层查询或父查询。在整个SELECT语句中,先计算子查询,然后将子查询的结果作为父查询的过滤条件,嵌套查询可以用多个简单的查询构成一个复杂的查询,用来增强SQL的查询能力。
1、带IN关键字的查询
带IN关键字的子查询是最常用的一类子查询,用于判定一个给定值是否存在与子查询的结果集中,使用IN关键字进行子查询是,内层查询语句仅仅返回一个数据列,其值将提供给外层查询进行比较操作。
#在学生表tb_student中,将学号出现在成绩表tb_score中(表明该学生选修了课程)的学生姓名查询出来
SELECT studentName
FROM tb_student
WHERE tb_student.studentNo IN
(SELECT DISTINCT tb_score, studentNo FROM tb_score);
或
SELECT DISTINCT studentName
FROM tb_student, tb_score
WHERE tb_student.studentNo = tb_score.studentNo;
说明:在处理这类子查询时MySQL实际上执行了两个操作,即先执行内层查询,再执行外层查询,内层查询的结果作为外层查询的比较条件。也可以使用NOT IN来判定一个给定值不属于子查询的结果。但是,这类表示否定的查询不能用连接查询来改写。
2、带比较运算符的子查询
带比较运算符的子查询是指父查询与子查询之间用用比较运算符进行连接,当用户能确定知道内层查询返回的是单值时,可以用=、>、<、>=、<=、!=(<>)等比较运算符构造子查询。
#查询班级“计算机17-1班”所有学生的学号、姓名
SELECT studentNo, studentName FROMtb_student
WHERE classNo =
(SELECT classNo FROM tb_class
WHERE className = ‘计算机17-1班’)
#查询与“李明”在同一个班学习的学生学号、姓名、班号
SELECT studentNo, studentName, classNo FROMtb_student s1
WHERE classNo =
(SELECT classNo FROM tb_ students s2
WHERE studentName=’李明’) AND studentName != ’李明’;
#上面的最后一个条件,是为了从结果集中去掉李明本人。
比较运算符还可以与ALL、SOME、ANY关键字一起构造子查询。ALL、SOME、ANY用于指定对比较运算符的限制,ALL用于指定表达式需要与子查询结果集中的每个值都进行比较当表达式与每个值都满足比较关系时,会返回TRUE,否则返回FALSE,SOME和ANY是同义词,表示表达式与子查询结果集中的某个值满足比较关系时,就返回TRUE,否则返回FALSE。
#查询男生中比某个女生出生年份晚的学生姓名和出生年份
SELECT studentName, YEAR(birthday) FROM tb_student
WHERE sex=’男’ AND YEAR(birthday)>ANY(
SELECT YEAR(birthday) FROM tb_student WHEREsex=’女’);
3、带EXISTS关键字的子查询
使用关键字EXISTS构建子查询时,系统对子查询进行运算以判断它是否返回结果集,如果子查询的结果集不为空,则EXISTS返回的结果为TRUE,此时外层查询语句将进行查询,如果子查询的结果集为空,则EXISTS返回的结果为FALSE,此时外层查询不进行查询。
由于带EXISTS的子查询只返回TRUE或FALSE,内层查询的SELECT 子句给出字段名称的实际意义,所以其目标列表达式通常用星号“*”。与EXISTS相对应的是NOT EXISTS,使用方法相同。
#查询选修了课程号为“31002”的学生姓名
SELECT studentName FROM tb_student a
WHERE EXISTS
(SELECT * FROM tb_score b
WHERE a.studentNo= b.studentNo AND courseNo=’31002’);
或
SELECT studentName FROM tb_student
WHERE studentNo IN
(SELECT studentNo FROM tb_score WHERE courseNo=’31002’);
说明:与关键字IN不同的是,外层的WHERE子句中关键字EXISTS前面没有指定内层查询结果集与外层查询的比较条件,故使用关键字EXISTS构造子查询时内层的WHERE子句中需要指定连接条件,即a.studentNo=b.studentNo。
PART02
联合查询
使用UNION关键字可以把来自多个SELECT语句的结果组合到一个结果集中,这种查询称为并(UNION)运算或联合查询。合并时,多个SELECT子句中对应的字段数和数据类型必须相同。下面不使用ALL关键字,执行的时候去掉重复的记录,所有返回的行都是唯一的,使用关键字ALL的作用是不去掉重复的记录,也不对结果进行自动排序。
语法格式是:
SELECT -FROM -WHERE
UNION [ALL]
SELECT -FROM -WHERE
[...UNION [ALL]
SELECT -FROM -WHERE]
例子:
#使用UNION查询选修了“管理学”或“计算机基础”的学生学号
SELECT studentNo FROM tb_score, tb_course
WHERE tb_score .courseNo= tb_course. courseNoAND courseName=’管理学’
UNION
SELECT studentNo FROM tb_score, tb_course
WHERE tb_score .courseNo= tb_course. courseNoAND courseName=’ 计算机基础’;
使用UNION语句需要注意以下几点:
UNION语句必须由两条或两条以上的SELECT语句组成,且彼此间用关键字UNION分隔。
UNION语句中的每个SELECT子句必须包含相同的列、表达式或聚合函数。
每个SELECT子句对应的目标列的数据类型必须兼容,目标列的数据类型不必完全相同,但必须是MySQL可以隐含转换的类型,例如,不同的数值类型或不同的日期类型。
第一个SELECT子句对应的目标列名会被作 为UNION语句结果集的列名称。
联合查询中只能使用一条ORDER BY自己或LIMIMT自己,且它们置于最后一条SELECT语句之后。
今天分享下MySQL中的子查询和联合查询,这对多层查询很有帮助,在工作中,我们常用的是子查询,因为很多数据都不是存储在一个表中,需要进行多层查询。
欢迎关注,访问更多精彩:数据之魅。
如需转载,请联系授权,谢谢合作。