使用子查询
本章介绍什么是子查询以及如何使用它们。
子查询
SELECT语句 是SQL的查询。迄今为止我们所看到的所有SELECT 语句都是简单查询,即从单个数据库表中检索数据的单条语句。
查询(query)任何SQL语句都是查询。但此术语一般指SELECT语句。
SQL还允许创建子查询(subquery),即嵌套在其他查询中的查询。
为什么要这样做呢?理解这个概念的最好方法是考察几个例子。
利用子查询进行过滤
我们课堂上使用的有两张表,学生信息表和成绩表两个表中。
学生表包含学号,籍贯,生日等信息
成绩表包含的有课程,成绩,考试时间,上课老师等信息
现在,假如需要列出考试成绩不及格的 所有同学,应该怎样检索?下
面列出具体的步骤。
1. 先在成绩表中查出成绩低于60分同学,找到这些同学的学号;
2. 然后学生信息表中按照学号检索出对应的同学名字
SELECT score FROM scores WHERE score < 60 ;
SELECT name FROM students WHERE
stuid in (“xxxxx”,”xxxxx);
select name,age from students where stu_id in (select stu_id from
scores where score < 60) ;
可见,在WHERE 子句中使用子查询能够编写出功能很强并且很灵活的SQL语句。对于能嵌套的子查询的数目没有限制,不过在实际使用时由于性能的限制,不能嵌套太多的子查询
列必须匹配在WHERE 子句中使用子查询(如这里所示),应该保证SELECT 语句具有与WHERE 子句中相同数目的列。通常,子查询将返回单个列并且与单个列匹配,但如果需要也可以使用多个列。
子查询和性能这里给出的代码有效并获得所需的结果。但是,使用子查询并不总是执行这种类型的数据检索的最有效的方法。
子查询:子查询时将一个查询语句嵌套在另一个查询语句中。
内层查询语句的查询结果,可以为外层查询语句提供查询条件,因为在特定的情况下,一个查询语句的条件需要另外一个查询语句来获取,例如现在需要从学生成绩表中查询计算机系学生的各科成绩,那么首先就必须知道哪些课程是计算机系学生选修的,因此必须查询计算机学生选修的课程,然后根据这些课程来查询计算机系学生的各科成绩,通过子查询,可以实现多表之间的查询,子查询中可能包IN,NOT IN,ANY,ALL,EXISTS和NOT EXSITS等关键字,子查询中还可能包含比较运算符,如‘=’,‘!=’,‘>’等;
带IN关键字的子查询
mysql> select * from employee
-> where d_id IN
-> (select d_id from department);
+------+------+--------+------+------+--------------------+
| num | d_id | name | age | sex | homeaddr |
+------+------+--------+------+------+--------------------+
| 1 | 1001 | 张三 | 26 | 男 | 北京市海定区 |
| 2 | 1002 | 李四 | 24 | 女 | 北京市昌平区 |
| 3 | 1001 | 王五 | 24 | 男 | 湖南长沙市 |
+------+------+--------+------+------+--------------------+
3 rows in set (0.00 sec)
mysql>
查询employee表中的记录,这些记录的d_id字段必须没有在department表中出现过。
mysql> select * from employee
-> where d_id NOT IN
-> (select d_id from department );
+------+------+------+------+------+----------+
| num | d_id | name | age | sex | homeaddr |
+------+------+------+------+------+----------+
| 4 | 1004 | Aric | 15 | 男 | England |
+------+------+------+------+------+----------+
1 row in set (0.00 sec)
带比较运算符的子查询
子查询可以使用比较运算符(=,!=,>,<,>=,<=,<>)等
示例数据表
mysql> select * from computer_stu,scholarship;
+------+------+-------+-------+-------+
| id | name | score | level | score |
+------+------+-------+-------+-------+
| 1001 | Lily | 85 | 1 | 90 |
| 1001 | Lily | 85 | 2 | 80 |
| 1001 | Lily | 85 | 3 | 70 |
| 1002 | Tom | 91 | 1 | 90 |
| 1002 | Tom | 91 | 2 | 80 |
| 1002 | Tom | 91 | 3 | 70 |
| 1003 | Jim | 87 | 1 | 90 |
| 1003 | Jim | 87 | 2 | 80 |
| 1003 | Jim | 87 | 3 | 70 |
| 1004 | Aric | 77 | 1 | 90 |
| 1004 | Aric | 77 | 2 | 80 |
| 1004 | Aric | 77 | 3 | 70 |
| 1005 | Lucy | 65 | 1 | 90 |
| 1005 | Lucy | 65 | 2 | 80 |
| 1005 | Lucy | 65 | 3 | 70 |
| 1006 | Andy | 99 | 1 | 90 |
| 1006 | Andy | 99 | 2 | 80 |
| 1006 | Andy | 99 | 3 | 70 |
| 1007 | Ada | 85 | 1 | 90 |
| 1007 | Ada | 85 | 2 | 80 |
| 1007 | Ada | 85 | 3 | 70 |
| 1008 | Jeck | 70 | 1 | 90 |
| 1008 | Jeck | 70 | 2 | 80 |
| 1008 | Jeck | 70 | 3 | 70 |
+------+------+-------+-------+-------+
24 rows in set (0.00 sec)
mysql>
从computer_stu表中查询获得一等奖学金的学生的学号,姓名和分数
mysql> select id,name,score from computer_stu where score >= (select score from scholarship where level=1);
+------+------+-------+
| id | name | score |
+------+------+-------+
| 1002 | Tom | 91 |
| 1006 | Andy | 99 |
+------+------+-------+
2 rows in set (0.00 sec)
在department表中查询那些部门没有年龄为24岁的员工;
mysql> select d_id,d_name from department
-> where d_id NOT IN
-> (select d_id from employee where age=24);
+------+-----------+
| d_id | d_name |
+------+-----------+
| 1003 | 销售部 |
+------+-----------+
1 row in set (0.00 sec)
带EXISTS 关键字的子查询
EXISTS关键字表示存在,使用EXISTS关键字时,内层查询不会反悔查询记录,而是返回一个真假值,当返回真是外层查询语句进行查询,当返回假时,外层语句不进行查询或者查询 不出任何结果。
例:如果department表中存在d_id取值为1003的记录,则查询employee表的记录:
mysql> select * from employee
-> where EXISTS
-> (select d_name from department where d_id =1003)
-> ;
+------+------+--------+------+------+--------------------+
| num | d_id | name | age | sex | homeaddr |
+------+------+--------+------+------+--------------------+
| 1 | 1001 | 张三 | 26 | 男 | 北京市海定区 |
| 2 | 1002 | 李四 | 24 | 女 | 北京市昌平区 |
| 3 | 1001 | 王五 | 24 | 男 | 湖南长沙市 |
| 4 | 1004 | Aric | 15 | 男 | England |
+------+------+--------+------+------+--------------------+
4 rows in set (0.00 sec)
mysql>
例:如果department表中存在d_id取值为1004的记录,则查询emloyee表的记录;
mysql>
mysql> select * from employee
-> where EXISTS
-> (select d_name from department where d_id=0);
Empty set (0.00 sec)
mysql>
例:如果department表中存在d_id取值为1003的记录,则查询employee表中age大于24的记录;
mysql>
mysql> select * from employee where age>24 and EXISTS
-> (select d_name from department where d_id=1003);
+------+------+--------+------+------+--------------------+
| num | d_id | name | age | sex | homeaddr |
+------+------+--------+------+------+--------------------+
| 1 | 1001 | 张三 | 26 | 男 | 北京市海定区 |
+------+------+--------+------+------+--------------------+
1 row in set (0.00 sec)
mysql>
带ANY关键字的子查询
ANY关键字表示满足其中任一条件,使用ANY关键字时,是要满足内层查询语句返回的结果中的任何一个,就可以通过该条件来执行外层查询语句。
例:查询到底哪位同学能获得奖学金:
mysql>
mysql> select * from computer_stu where score >= ANY
-> (select score from scholarship);
+------+------+-------+
| id | name | score |
+------+------+-------+
| 1001 | Lily | 85 |
| 1002 | Tom | 91 |
| 1003 | Jim | 87 |
| 1004 | Aric | 77 |
| 1006 | Andy | 99 |
| 1007 | Ada | 85 |
| 1008 | Jeck | 70 |
+------+------+-------+
7 rows in set (0.00 sec)
mysql>
带ALL关键字的子查询
ALL关键字表示满足所有条件,使用ALL关键字时,只有满足内层查询语句返回的所有结果,才可以执行外层查询语句。
例:从computer_stu表中查询出那些同学可以获得一等奖学金;
mysql>
mysql> select * from computer_stu
-> where score >= ALL
-> (select score from scholarship);
+------+------+-------+
| id | name | score |
+------+------+-------+
| 1002 | Tom | 91 |
| 1006 | Andy | 99 |
+------+------+-------+
2 rows in set (0.00 sec)
mysql>
注:ANY关键字和ALL关键字的使用方式是一样的,但是俩这有很大的区别,使用ANY关键字时,只要满足内层查询语句返回的结果中的任何一个,就可以通过该条件来执行外层查询语句,而ALL关键字刚好相反,只有满足内层查询语句返回的所有结果,才可以执行外层查询语句。
合并查询结果(具有去重功能)
合并查询结果是将多个select语句的查询结果合并在一起,因某种情况下,需要将几个select语句查询出来的结果合并起来显示,例如现在需要查询公司甲和公司乙这俩个公司所有的员工信息,然后将俩次的查询结果合并到一起,进行合并操作使用 UNION和UNION ALL关键字。
格式:select 语句1
UNION | UNION ALL
select 语句2
UNION | UNION ALL
例:从department表和employee表中查询d_id字段的取值,然后通过UNION关键字将结果合并到一起。
mysql>
mysql> select d_id from department
-> UNION
-> select d_id from employee;
+------+
| d_id |
+------+
| 1001 |
| 1002 |
| 1003 |
| 1004 |
+------+
4 rows in set (0.00 sec)
mysql>
Robbers:The content of this article is for reference only. If a mistake is found, it can be a private author. If it is found identical, please inform the author that I will indicate the source.