【MySQL必知必会】第14章使用子查询

SELECT语句是SQL的查询。迄今为止我们所看到的所有SELECT语句都是简单查询,即从单个数据库表中检索数据的单条语句

SQL还允许创建子查询(subquery),即嵌套在其他查询中的查询。为什么要这样做呢?理解这个概念的最好方法是考察几个例子。

利用子查询进行过滤

在这里插入图片描述
在这里插入图片描述
注意了,如果某个表的查询需要用到其他表的查询的结果的时候,就要用子查询了。

比如,我们想查出订购了TNT2的所有用户,怎么办?
第一步,我们找出来TNT2的订单编号。
在这里插入图片描述
下一步,查询具有订单20005和20007的客户ID.

SELECT cust_id FROM orders WHERE order_num IN(20005,20007);

在这里插入图片描述
是不是感觉特别low? low就对了。
第二个查询要用到第一个查询的结果,所以我们可以把第一个查询变成一个子查询。

SELECT cust_id FROM orders WHERE order_num IN (SELECT order_num FROM orderitems WHERE prod_id='TNT2');

在这里插入图片描述
在SELECT语句中,子查询总是从内向外处理。在处理上面的SELECT语句时,MySQL实际上执行了两个操作:
首先,它执行下面的查询:

SELECT order_num FROM orderitems WHERE prod_id='TNT2'

此查询返回两个订单号:20005和20007。然后,这两个值以IN操作符要求的逗号分隔的格式传递给外部查询的WHERE子句.
因此外查询变成了:

SELECT cust_id FROM orders WHERE order_num IN(20005,20007);

包含子查询的SELECT语句难以阅读和调试。所以要注意缩进。

别忘了,我们只是拿到了用户的ID,还没拿到信息呢。继续运用子查询。

SELECT cust_name, cust_contact FROM customers WHERE cust_id IN (SELECT cust_id FROM orders WHERE order_num IN (SELECT order_num FROM orderitems WHERE prod_id='TNT2'));

在这里插入图片描述

最外层查询确实返回所需的数据。

注意!!!
列必须匹配 在WHERE子句中使用子查询(如这里所示),应该保证SELECT语句具有与WHERE子句中相同数目的列。通常,子查询将返回单个列并且与单个列匹配,但如果需要也可以使用多个列。

也就是说,外层SELECT中查的列数,与WHERE中的列数应该是相同的。

虽然子查询一般与IN操作符结合使用,但也可以用于测试等于(=)、不等于(<>)等。
子查询效率一般。最好用Join

作为计算字段使用子查询

使用子查询的另一方法是创建计算字段。假如需要显示customers表中每个客户的订单总数。订单与相应的客户ID存储在orders表中。

为了执行这个操作,遵循下面的步骤。

  • (1) 从customers表中检索客户列表。
  • (2) 对于检索出的每个客户,统计其在orders表中的订单数目。

customers的表结构是这样的:
在这里插入图片描述
而orders表是这样的:
在这里插入图片描述

我们开始:
可使用SELECT COUNT(*)对表中的行进行计数,并且通过提供一条WHERE子句来过滤某个特定的客户ID,可仅对该客户的订单进行计数。例如,下面的代码对客户10001的订单进行计数:

SELECT COUNT(*) AS orders FROM orders WHERE cust_id=10001;

在这里插入图片描述

为了对每个客户执行COUNT(*)计算,应该将COUNT(*)作为一个子查询。请看下面的代码:

SELECT cust_name, cust_state, (SELECT COUNT(*) FROM orders WHERE orders.cust_id=customers.cust_id) AS orders FROM customers ORDER BY cust_name;

在这里插入图片描述
该子查询对检索出的每个客户执行一次。在此例子中,该子查询执行了5次,因为检索出了5个客户。

下面的语句告诉SQL比较orders表中的cust_id与当前正从customers表中检索的cust_id:

WHERE orders.cust_id=customers.cust_id

相关子查询
即,涉及外部查询的子查询。任何时候只要列名可能有多义性,就必须使用这种语法(表名和列名由一个句点分隔)。不然会造成混乱。

写子查询时,要先写内层,再写外层,一步一步来。不要着急。

发布了464 篇原创文章 · 获赞 21 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/weixin_41687289/article/details/105339988