(二十六)子查询

 

一、子查询的定义:

  子查询是将一个查询语句嵌套在另一个查询语句中;

  在特定情况下,一个查询语句的条件需要另一个查询语句来获取,内层查询(inner query)语句的查询结果,可以为外层查询(outer query)语句提供查询条件。

二、子查询分类

子查询有两种分类方式:按位置分类和按结果分类。

① 按位置分类:子查询(select语句)在外部查询(select语句)出现的位置

1.from子查询:子查询跟在from之后;
2.where子查询:子查询出现在where条件中;
3.exists子查询:子查询出现在exists里面;
4.in子查询:子查询出现在in 里面。

② 按结果分类:根据子查询得到的数据进行分类—理论上任何一个查询得到的结果都可以理解为一个二维表

1.标量子查询:子查询得到的结果是一行一列;
2.列子查询:子查询得到的结构是一列多行;
3.行子查询:子查询的得到的结果是一行多列(也可以是多行多列);
前三者出现的位置都是在where之后;
4.表子查询:子查询得到的结果是多行多列(位置在from之后)。

③按照场合分类

  • 作为主查询的结果数据:select c1,(select f1 from tab2) as f11 from tab1; #这里子查询应该只有一个数据(一行一列,标量子查询)
  • 作为主查询的条件数据:select c1 from tab1 where c1 in (select f1 from tab2); #这里子查询可以是多个数据(多行一列,列子查询,以及标量子查询,实际上行子查询也可能,但极少)
  • 作为主查询的来源数据:select c1 from (select f1 as c1, f2 from tab2) as t2; #这里子查询可以是任意查询结果(表子查询)。

 

 

三、 使用子查询原则

  • 一个子查询必须放在圆括号中
  • 将子查询放在比较条件的右边以增加可读性。
  •  子查询不包含 ORDER BY 子句。对一个 SELECT 语句只能用一个 ORDER BY 子句,并且如果指定了它就必须放在主 SELECT 语句的最后
  • 在子查询中可以使用两种比较条件:单行运算符(>, =, >=, <, <>, <=) 和多行运算符(IN, ANY, ALL)。

四、实例分析

环境搭建:employee雇员表、department部门表、TENNIS数据库

  1. 不相关子查询

  不相关,主查询和子查询是不相关的关系。也就是意味着在子查询中没有使用到外部查询的表中的任何列。

  先执行子查询,然后执行外部查询

标量子查询(scalar subquery):返回1行1列一个值

  因为是标量子查询,结果是一个值,所以可用来进行算数运算。

  可以使用 = > < >= <= <> 操作符对子查询的结果进行比较:

  • 查找部门是"科技部"的所有员工

思路:先找到科技部的id,然后利用这个查询结果,作为员工表的查询条件

select d_id,name from employee 

where d_id =(select d_id from department where d_name='科技部');

②行子查询(row subquery):返回的结果集是 1 行 N 列(即1行中有多个值)

  使用行表达式进行比较,可以使用 = > < >= <= <> in操作符

  • 获取和100号球员性别相同并且居住在同一城市的球员号码

 select playerno from players 
   where (sex, town) = (
    select sex, town 
    from players 
    where playerno = 100);
 

③列子查询(column subquery):返回的结果集是 N 行 1列

  必须使用 IN、ANY 和 ALL 操作符对子查询返回的结果进行比较

注意:ANY 和 ALL 操作符不能单独使用,其前面必须加上单行比较操作符= > < >= <= <>

 IN:在指定项内,同 IN(项1,项2,…)。

使用in进行子查询,这个我们在日常写sql的时候是经常遇到的。in的意思就是指定的一个值是否在这个集合中,如何在就返回TRUE;否则就返回FALSE了。

in是“=any”的别名,在使用“=any”的地方,我们都可以使用“in”来进行替换。

有了in,肯定就有了not in;not in并不是和<>any是同样的意思,not in和<>all是一个意思。

 

    ANY:与比较操作符联合使用,ANY关键字必须接在一个比较操作符的后面,表示与子查询返回的任何值比较为 TRUE ,则返回 TRUE 。(ANY关键字表示满足其中任一条件)

any关键词的意思是“对于子查询返回的列中的任何一个数值,如果比较结果为TRUE,就返回TRUE”。

好比“10 >any(11, 20, 2, 30)”,由于10>2,所以,该该判断会返回TRUE;只要10与集合中的任意一个进行比较,得到TRUE时,就会返回TRUE。

 

    ALL:与比较操作符联合使用,ALL关键字必须接在一个比较操作符的后面,表示与子查询返回的所有值比较都为 TRUE ,则返回 TRUE 。(表示该操作数的值必须跟列子查询的所有值都满足给定的比较运算,才算满足了条件。)

  •   实例1(in):获取球员性别为女的所有球员的球员号,名字及所在城市。

mysql> select playerno, name, town 
from players 
where playerno in 
    (select playerno 
    from players 
    where sex = 'F');

查询过程:先找到性别为女的集合,然后外层每一条记录一条记录进行比较

  • 获取至少比同城的另一球员年轻的所有球员的号码,日期和居住城市。

mysql> select playerno, birth_date, town 
from players as p1 
where birth_date > any (至少一个)
    (select birth_date 
    from players as p2 
    where p1.town = p2.town);

  • 获取最老球员的号码,名字及生日。(即出生日期数值小于或等于所有其它球员的球员)

mysql> select playerno, name, birth_date 
from players 
where birth_date <= all (所有)
    (select birth_date 
    from players);

查询过程:内部找到所有年龄,外层<=所有,即值 最小,但年龄最大

找出所有产品中最贵的

select * from product where price>=all
(
  select price from product
);

④表子查询

作为主查询的来源数据:select c1 from (select f1 as c1, f2 from tab2) as t2; #这里子查询可以是任意查询结果(表子查询)。

 

 

参考:https://blog.csdn.net/jesseyoung/article/details/40108781 

posted @ 2019-07-15 12:47  测试开发分享站  阅读(212)  评论(0编辑  收藏  举报