第九章:第21节 MySQL基础篇——数据查询语言DQL(子查询、联合查询)

更新于:2017-08-01 20:39:58

什么叫子查询

一个查询,通常就是一个select语句(即出现一次select关键字)

但,如果在一个select查询语句中,又出现了select查询语句,此时就称后者为“子查询”,前者就是“主查询”


形式:

selelct 字段或表达式或(子查询1) [as 别名] from 表名或(子查询2) where 字段或表达式或(子查询3) 的条件判断


注意:

每个位置所放置的子查询结果,应该符合该位置的数据需求。

通常:

子查询1应该是一个“数据结果”。

子查询2可以是“任意结果”,此位置的查询结果,通常作为数据源,可以给一个别名

子查询3可以是一个数据或一列数据甚至是一行数据


子查询按结果分类:

表子查询 一个子查询返回的结果理论上是多行多列”的时候。此时可以当做一个“表”来使用,通常是放在from后面。

行字查询 一个子查询返回的结果理论上是一行多列”的时候。此时可以当做一个“行”来使用,通常放在“行比较语法”中。

列子查询 一个子查询返回的结果理论上是多行一列”的时候。此时可以当做“多个值”使用,类似这种:(5, 17, 8, 22)。

标量子查询:一个子查询返回的结果理论上是一行一列”的时候。此时可以当做“一个值”使用,类似这种:select 5 as c1; 或select ...where a = 17,或select ... where b > 8;

按使用场合分:

作为主查询的结果数据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; #这里子查询可以是任意查询结果(表子查询)。


常见子查询及相关关键字


比较运算符中使用子查询

形式为: 操作数 比较运算符 (标量子查询)

操作数通常是一个字段。

含义:判断该操作数(字段)的值是否满足该比较运算符所设定的比较结果。

其实就是相当于最简单的这种形式: id > 5;

举例:

数据源 表product:

1.png


需求:找出所有大于平均价的商品。

第一步:找平均价:

select avg(price) as avg_price  from  product;

1.png

 

第二部:找商品:

select * from product  where price  > 4287.7; ==

select * from product  where price 〉(select avg(price) as avg_price  from  product);

1.png


使用in子查询

in的基本语法形式为:

where  操作数  in (1,值2....

in子查询就是:

where  操作数  in ( 列子查询 );

含义:

表示该操作数(字段值) 等于 该子查询的其中任意一个只,就算满足条件。


类别表 product_type:

1.png


举例:

找出所有带“电”字的类别的产品

第一步:找出所有带“电”字的类别ID

select id from product_type where name like '%电%';

1.png


第二步:根据结果找出这些类别的产品:


select * from product  where  protype_id in (1,3);==>

select * from product  where  protype_id in ( 

   select id from product_type where name like '%电%'

);

1.png


使用any子查询

使用形式:

where  操作数  比较运算符   any ( 列子查询 );

说明:

1操作数通常仍然是字段名

2比较运算符就是常规的〉  〉=  <   <=  =   <> 

3列子查询也可以是标量子查询,都表示“若干个数据值”

含义:

表示该操作数的值只要跟列子查询的任意一个值满足给定的比较运算,就算满足了条件——就是只要有一个成就成。

考察一个特定情况:

where  操作数  =  any ( 列子查询 );

则其完全相当于:

where  操作数  in  ( 列子查询 );

举例:

找出所有带“电”字的类别的产品

1.png


使用all子查询

where  操作数  比较运算符   all ( 列子查询 );

说明:

1操作数通常仍然是字段名

2比较运算符就是常规的〉  〉=  <   <=  =   <> 

3列子查询也可以是标量子查询,都表示“若干个数据值”

含义:

表示该操作数的值必须跟列子查询的所有值都满足给定的比较运算,才算满足了条件。

 

举例:

找出产品表中的价格最高的产品。

分析:最高价的产品的价格会大于等于所有产品价格。


1.png


方法二:

1.png


使用some的子查询

someany的同义词。一样用。

使用exists的子查询

以前所学:

if  exist

或者:

if  not  exists

以前其含义通常是:存在某数据(通常是一个表)

 

现在,该词也同样用于子查询,表示同样的含义“存在”

 

形式:

where  exists  (子查询);

含义:

如果该子查询有结果数据(无论什么数据,只要大于等于1行),则就是true,否则为false

 

举例:

找出具有在售商品的那些类别:


1.png


使用not  exists子查询

含义跟exists子查询相反。

举例:

找出还没有在售商品的类别:

1.png


了解一下:实际上,这种exists(或not  exists)子查询,如果涉及到2个表(或以上),其内部其实会自动进行“连接查询”,且其逻辑过程较为负责,而且还不明确,通常认为属于效率较低的子查询,尽量少用。


联合查询

联合查询的关键字是: union

连接查询的关键字是: join

但,在mysql手册中, join这个连接查询,往往都翻译为“联合查询”

但在绝大多数的中文书籍和文章中,join被翻译为“连接查询”

 

基本含义

联合查询就是将两个select语句的查询结果“层叠”到一起成为一个“大结果”。

两个查询结果的能够进行“联合”的先觉条件是:结果字段数相等。

1.png

语法形式:

select 语句1

union  [ALL | DISTINCT]

select 语句2

说明:

1,两个select语句的输出段(结果字段)一样数目一样,应用中通常类型一样才有意义。

2,结果集中的字段以第一个select语句的字段为准。

3,第一个select语句的字段可以做别名,但如果做别名,则后续的wheregrouporder等子句应该用该别名。

4,联合查询默认是会消除重复项的(DISTINCT),要想不消除,则必须明确些“ALL”。

5,如果要对整个联合结果进行排序或limit,则应该对各自的select语句加括号:

select 语句1

union

select 语句2

order  by .....  limit ....

1.png

1.png



大总结说明:


数据的查询:基本查询、连接查询、子查询、联合查询就简单地介绍完了。想要学好数据库的查询,需要大家自己多去练习才能学好。下节楠神会出一些练习题供大家强化学习。


说说这几种查询哪个最重要?


用得最多的最实用的还是基本查询,反正楠神在开发项目时除了单表查询(基本查询)很少用其他,只有在不得已的情况下才会用其他查询方式。


楠神在开发项目时,本应该使用连接查询的,我都是把它拆分成多条单表查询,再依靠PHP的for循环来获得连接查询的结果。为什么这样做呢?后面的学习我会做介绍的。


虽然楠神在开发项目时不怎么用连接查询、子查询,不代表它们就不重要了,肯定要熟练应用的,尤其是连表查询。这应该是程序员的基本功。


子查询比较消耗资源,能用连表获得结果的,尽量避免子查询。


联合查询用的不多。


本节学习代码》》》