子查询是指一个查询语句嵌套在另一个查询语句内部的查询。在 SELECT 子句中先计算子查询,子查询结果作为外层另一个查询的过滤条件,查询可以基于一个表或者多个表。子查询中常用的操作符有 ANY(SOME)、ALL、IN、EXISTS。子查询可以添加到 SELECT、UPDATE 和 DELETE 语句中,而且可以进行多层嵌套。子查询中也可以使用比较运算符,如“<”、“<=”、 “>”,“>=”和“!=”等。
1. 带ANY、SOME关键字的子查询
ANY 和 SOME 关键字是同义词,表示满足其中任一条件,它们允许创建一个表达式对子查询的返回值列表进行比较,只要满足内层子查询中的任何一个比较条件,就返回一个结果作为外层查询的条件。
mysql> select * from tbl1; +------+ | num1 | +------+ | 1 | | 5 | | 13 | | 27 | +------+ mysql> select * from tbl2; +------+ | num2 | +------+ | 6 | | 14 | | 11 | | 20 | +------+【例】返回 tbl2 表的所有 num2 列,然后将 tbl1 中的 numl 的值与之进行比较,只要大于 num2 的任何1个值,即为符合查询条件的结果, SQL语句如下:
mysql> SELECT num1 FROM tbl1 WHERE num1 > ANY (SELECT num2 FROM tbl2); +------+ | num1 | +------+ | 13 | | 27 | +------+
2. 带 ALL 关键字的子查询
ALL关键字与 ANY 和 SOME 不同,使用 ALL 时需要同时满足所有内层查询的条件。
ALL 关键字位于一个比较操作符的后面,表示与子查询返回的所有值比较为 TRUE,则返回TRUE。
【例】返回 tbl1 表中比 tbl2 表中,num2 列的所有值都大的值。SQL语句如下:
mysql> SELECT num1 FROM tbl1 WHERE num1 > ALL (SELECT num2 FROM tbl2); +------+ | num1 | +------+ | 27 | +------+
3. 带 EXISTS 关键字的子查询
EXISTS 关键字后面的参数是一个任意的子查询,系统对子查询进行运算以判断它是否返回行,如果至少返回一行,那么EXISTS 的结果为 true,此时外层查询语句将进行查询;如果子查询没有返回任何行,那么 EXISTS 返回的结果是 false,此时外层语句将不进行查询。 【例】查询 suppliers 表中是否存在 s_id=107 的供应商,如果存在,则查询 fruis 表中的记录。SQL语句如下:
mysql> SELECT * FROM fruits -> WHERE EXISTS -> (SELECT s_name FROM suppliers WHERE s_id=107); +------+------+------------+---------+ | f_id | s_id | f_name | f_price | +------+------+------------+---------+ | a1 | 101 | apple | 5.20 | | a2 | 103 | apricot | 2.20 | | b1 | 101 | blackberry | 10.20 | | b2 | 104 | berry | 7.60 | | b5 | 107 | xxxx | 3.60 | | bs1 | 102 | orange | 11.20 | | bs2 | 105 | melon | 8.20 | | c0 | 101 | cherry | 3.20 | | l2 | 104 | lemon | 6.40 | | m1 | 106 | mango | 15.60 | | m2 | 105 | xbabay | 2.60 | | m3 | 105 | xxtt | 11.60 | | o2 | 103 | coconut | 9.20 | | t1 | 102 | blanana | 10.30 | | t2 | 102 | grape | 5.30 | | t4 | 107 | xbababa | 3.60 | +------+------+------------+---------+
NOT EXISTS 与 EXISTS 的使用方法相同,返回的结果相反。子查询如果至少返回一行,那么 NOT EXISTS 的结果为 false,此时外层查询语句将不进行查询; 如果子查询没有返回任何行,那么 NOT EXISTS 返回的结果是 true,此时外层语句将进行查询。
mysql> SELECT * FROM fruits -> WHERE NOT EXISTS -> (SELECT s_name FROM suppliers WHERE s_id=107); Empty set (0.00 sec)
4. 带 IN 关键字的子查询
用 IN 关键字进行子查询时,内层查询语句只返回一个数据列,这个数据列里的值将提供给外层查询语句进行比较操作。
mysql> SELECT * FROM orderitems; +-------+--------+------+----------+------------+ | o_num | o_item | f_id | quantity | item_price | +-------+--------+------+----------+------------+ | 30001 | 1 | a1 | 10 | 5.20 | | 30001 | 2 | b2 | 3 | 7.60 | | 30001 | 3 | bs1 | 5 | 11.20 | | 30001 | 4 | bs2 | 15 | 9.20 | | 30002 | 1 | b3 | 2 | 20.00 | | 30003 | 1 | c0 | 100 | 10.00 | | 30004 | 1 | o2 | 50 | 2.50 | | 30005 | 1 | c0 | 5 | 10.00 | | 30005 | 2 | b1 | 10 | 8.99 | | 30005 | 3 | a2 | 10 | 2.20 | | 30005 | 4 | m1 | 5 | 14.99 | +-------+--------+------+----------+------------+
mysql> SELECT * FROM orders; +-------+---------------------+-------+ | o_num | o_date | c_id | +-------+---------------------+-------+ | 30001 | 2008-09-01 00:00:00 | 10001 | | 30002 | 2008-09-12 00:00:00 | 10003 | | 30003 | 2008-09-30 00:00:00 | 10004 | | 30004 | 2008-10-03 00:00:00 | 10005 | | 30005 | 2008-10-08 00:00:00 | 10001 | +-------+---------------------+-------+
【例】在orderitems 表中查询 f_id 为 c0 的订单号,并根据订单号查询具有订单号的客户 c_id,SQL语句如下:
mysql> SELECT c_id FROM orders WHERE o_num IN -> (SELECT o_num FROM orderitems WHERE f_id='c0'); +-------+ | c_id | +-------+ | 10004 | | 10001 | +-------+
MySQL 实际上执行了两个操作过程,即先执内层子查询,再执行外层查询,内层查询结果作为外部查询的比较条件。
在SELECT 语句中可以使用 NOT IN 关键字,其作用与 IN 正好相反。
【例】在 SELECT 语句中使用 NOT IN 关键字。mysql> SELECT c_id FROM orders WHERE o_num NOT IN -> (SELECT o_num FROM orderitems WHERE f_id='c0'); +-------+ | c_id | +-------+ | 10001 | | 10003 | | 10005 | +-------+
5. 带比较运算符的子查询
利用子查询时还可以使用比较运算符,如“<”、“<=”、 “>”,“>=”和“!=”等。
【例】在 suppliers 表中查询 s_city 等于 Tianjin的供应商的 s_id,然后在 fruits 表中查询所有非该供应商提供的水果的种类。SQL 语句如下:
mysql> SELECT s_id , f_name FROM fruits -> WHERE s_id <> -> (SELECT s1.s_id FROM suppliers AS s1 WHERE s1.s_city = 'Tianjin'); +------+---------+ | s_id | f_name | +------+---------+ | 103 | apricot | | 104 | berry | | 107 | xxxx | | 102 | orange | | 105 | melon | | 104 | lemon | | 106 | mango | | 105 | xbabay | | 105 | xxtt | | 103 | coconut | | 102 | blanana | | 102 | grape | | 107 | xbababa | +------+---------+