本文共 5573 字,大约阅读时间需要 18 分钟。
多行子查询通过多行比较操作符来实现,其返回值为多行。常用的多行比较操作符包括:IN 和 NOT IN、ALL 和 ANY/SOME、EXISTS 和 NOT EXISTS 操作符,本文主要介绍这几种多行比较操作符的应用。
IN 子查询是指在外层查询和子查询之间用 IN 进行连接,判断某个属性列是否在子查询的结果中,其返回的结果中可以包含零个或者多个值。在 IN 子句中,子查询和输入多个运算符的数据的区别在于,使用多个运算符输入时,一般都会输入两个或者两个以上的数值,而使用子查询时,不能确定其返回结果的数量。但是,即使子查询返回的结果为空,语句也能正常运行。
由于在子查询中,查询的结果往往是一个集合,所以 IN 子查询是子查询中最常用的。IN 子查询语句的操作步骤可以分成两步:
【示例01】获取 tb_book 图书表和 tb_book_author 作者表中具有相同部门 (tb_author_department) 的作者所写的图书信息。SQL 语句如下:
SELECT * FROM tb_bookWHERE book_sort IN(SELECT tb_author_department FROM tb_book_author WHERE tb_book.book_sort=tb_book_author.tb_author_department)ORDER BY tb_book.book_price;
查询结果如下图所示:
【示例02】查询在 tb_book 图书表中列出,而在 tb_book_author 作者表中没有列出的作者所在部门的图书信息。SQL 语句如下:
SELECT * FROM tb_bookWHERE book_sort NOT IN(SELECT tb_author_department FROM tb_book_author);
查询结果如下图所示:
【练习1】在 course 和 grade 表中,查询没有学生参加考试的课程信息。 【练习2】在 student 表中,查询 课程成绩
大于 98 分的学生信息。
EXISTS 子查询的功能是判断子查询的返回结果中是否有数据行。如果子查询返回的结果是空集,则判断为不存在,即 EXISTS 失败,NOT EXISTS 成功。如果子查询返回至少一行的数据记录,则判断存在,即 EXISTS 成功,NOT EXISTS 失败。由于 EXISTS 子查询中不需要返回具体值,所以该子查询的选择列表常用 SELECT *
格式,其外层的 WHERE 子句中也不需要指定列名。
EXISTS 通常都和相关子查询一起使用。在使用相关子查询时,对外表中的每一行,子查询都要运行一遍,该行的值也要在子查询的 WHERE 子句中被使用。这样,通过 EXISTS 子句就能将外层表中的各行数据依次与子查询处理的内层表中的数据进行存在性比较,得到需要的结果。关键字 EXISTS 引入子查询的语法特点如下:
*
组成的。因为只是测试满足子查询的数据行的存在性,所以在子查询的 SELECT 列表清单中加入列名没有实际意义。1、比较使用 EXISTS 和 IN 的查询
EXISTS 子查询和 IN 操作符可以实现同一个功能,但是两者之间是有区别的。第 1 个查询使用 EXISTS,而第 2 个查询使用 IN。注意两个查询返回相同的信息。
(1) 使用谓词 EXISTS 的 SQL 语句如下:
SELECT DISTINCT goods_nameFROM goodsWHERE EXISTS( SELECT * FROM brand WHERE cat_id = goods.cat_id AND name='索尼/SONY');
(2) 使用谓词 IN 的 SQL 语句如下:
SELECT DISTINCT goods_nameFROM goodsWHERE cat_id IN( SELECT cat_id FROM brand WHERE cat_id = goods.cat_id AND name='索尼/SONY');
这两种方法返回相同的查询结果,如下图所示:
通过 orderform 订单表与 user_address 用户地址表,查找两个表中相同国家的收货人姓名。通过两种查询方法:
(1) 使用 EXISTS 的 SQL 语句如下:
SELECT consignee,country FROM orderformWHERE EXISTS(SELECT country FROM user_address WHERE orderform.country=user_address.country);
(2) 使用 “=ANY” 的 SQL 语句如下:
SELECT consignee,country FROM orderformWHERE country = ANY(SELECT country FROM user_address);
这两种方法返回相同的查询结果。
【示例03】获取 tb_book 图书表和 tb_book_author 作者表中,具有相同部门的作者所写的图书信息。SQL 语句如下:
SELECT * FROM tb_bookWHERE EXISTS(SELECT * FROM tb_book_author WHERE tb_book.book_sort=tb_book_author.tb_author_department)ORDER BY tb_book.book_price;
查询结果如下图所示:
3、NOT EXISTS 子查询实现两个表的差集
与 EXISTS 相对应的是 NOT EXISTS。使用 NOT EXISTS 后,如果子查询的结果为空,则外层的 WHERE 子句返回 TRUE。
【示例04】获取 tb_book 图书表与 tb_book_author 作者表中相同部门以外的图书信息。SQL 语句如下:
SELECT * FROM tb_bookWHERE NOT EXISTS(SELECT tb_author_department FROM tb_book_author WHERE tb_book.book_sort=tb_book_author.tb_author_department)ORDER BY tb_book.book_price;
【练习3】查询没参加考试的学生信息。
【练习4】查询报名人数大于平均报名人数的课程信息。 【练习5】查询学生选课表(StuCou) 中报名状态为 "报名"的课程名。 【练习6】查询已经报名选修课程的学生信息,要求显示学号和姓名。ALL、SOME 和 ANY 是量词,允许将比较运算符左边的单值与生成单列但多行结果集的子查询(在比较运算符的右边)相比较。如果 WHERE 子句中的子查询生成多个值的单列结果,将终止以下形式的查询:
SELECTFROM { =|<>|>|>=|<|<=} WHERE
下面通过几个例子来了解如何使用量词实现多行子查询。
(1) 在 goods 商品信息表中查询同类商品中,售价高于平均售价的商品信息。SQL 语句如下:
SELECT cat_id,goods_name,shop_priceFROM goodsWHERE shop_price < ( SELECT AVG(shop_price) FROM goods GROUP BY cat_id);
执行 SQL 语句,如下图所示:
SELECTFROM { =|<>|>|>=|<|<=} { SOME|ANY|ALL} WHERE
如果子查询的单列结果表有不止一行的数据,此时将不会终止查询。而是将 <expression>(比较运算符左边) 的值与比较运算符右边的子查询返回的每个值进行比较。
(2) 改写上面的 SQL 语句,加入量词 SOME,再次执行查询语句,就不会出现错误信息。SQL 语句如下:
SELECT cat_id,goods_name,shop_priceFROM goodsWHERE shop_price < SOME( SELECT AVG(shop_price) FROM goods GROUP BY cat_id);
查询结果如下图所示:
ALL 操作符比较子查询返回列表中的每一个值。<ALL
为小于最小的;>ALL
为大于最大的;而 =ALL
则没有返回值,因为在等于子查询的情况下,返回列表中的所有值是不符合逻辑的。
ALL 允许将比较运算符前面的单值与比较运算符后面的子查询返回值的集合中的每一个值相比较。另外,仅当所有(ALL)的比较运算符左边的单值与子查询返回值的集合中的每一个值的比较都求值为 TRUE 时,比较判式(以及 WHERE子句)才求值为 TRUE。
【示例05】获取所有商品售价低于本身品牌的平均售价的商品信息。SQL 语句如下:
SELECT cat_id,goods_name,shop_priceFROM goodsWHERE shop_price < ALL( SELECT AVG(shop_price) FROM goods GROUP BY cat_id);
查询结果如下:
ANY 操作符比较子查询返回列表中的每一个值。<ANY
为小于最大的;>ANY
为大于最小的;而 =ANY
为等于 IN。ANY 允许将比较运算符前面的单值与比较运算符后面的子查询返回值的集合中的每一个值相比较。另外,仅当所有(ANY) 的比较运算符左边的单值与子查询返回值的集合中的一个值的比较求值为 TRUE 时,比较判式(以及WHERE子句)的求值就为 TRUE。
【示例06】获取商品的售价比平均售价高的商品信息,并按商品品牌进行划分。SQL 语句如下:
SELECT cat_id,goods_name,shop_priceFROM goodsWHERE shop_price > ANY( SELECT AVG(shop_price) FROM goods GROUP BY cat_id);
查询结果如下图所示:
总结:本章主要介绍了多行子查询。多行子查询通过多行比较操作符来实现,比较常用的多行比较操作符包括:IN 和 NOT IN、ALL 和 ANY/SOME、 EXISTS 和 NOT EXISTS 操作符。
转载地址:http://qcik.baihongyu.com/