11.子查询(4.1及以上)

本文详细介绍了如何利用子查询进行复杂的数据库过滤操作,包括从多个表中检索特定信息。通过逐步分解查询过程,解释了如何通过子查询找出订购物品TNT2的所有客户,以及如何使用子查询计算每个客户的订单总数。同时强调了子查询在WHERE子句中的应用,以及在性能和可读性方面的考虑。虽然子查询提供了强大的功能,但在某些情况下可能不是最有效的方法。
摘要由CSDN通过智能技术生成

利用子查询进行过滤

本书所有章中使用的数据库表都是关系表(关于每个表及关系的描述,请参阅附录B)。订单存储在两个表中。对于包含订单号、客户ID、 订单日期的每个订单,orders表存储一行。各订单的物品存储在相关的 orderitems表中。orders表不存储客户信息。它只存储客户的ID。实际的客户信息存储在customers表中

假如需要列出订购物品TNT2的所有客户,应该怎样检索?下 面列出具体的步骤。

(1) 检索包含物品TNT2的所有订单的编号。

(2) 检索具有前一步骤列出的订单编号的所有客户的ID。

(3) 检索前一步骤返回的所有客户ID的客户信息。

合并成一句后,查询语句由内向外处理。

包含子查询的SELECT语句难以阅读和调试,特 别是它们较为复杂时更是如此。如上所示把子查询分解为多行 并且适当地进行缩进,能极大地简化子查询的使用。

现在得到了订购物品TNT2的所有客户的ID。下一步是检索这些客户 ID的客户信息。检索两列的SQL语句为

可以把其中的WHERE子句转换为子查询而不是硬编码这些客户ID:

为了执行上述SELECT语句,MySQL实际上必须执行3条SELECT语句。最里边的子查询返回订单号列表,此列表用于其外面的子查询的WHERE子句。外面的子查询返回客户ID列表,此客户ID列表用于最外层查询的WHERE子句。最外层查询确实返回所需的数据。 可见,在WHERE子句中使用子查询能够编写出功能很强并且很灵活的 SQL语句。对于能嵌套的子查询的数目没有限制,不过在实际使用时由于 性能的限制,不能嵌套太多的子查询

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

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

这里给出的代码有效并获得所需的结果。但是,使用子查询并不总是执行这种类型的数据检索的最有效 的方法。

作为计算字段使用子查询

使用子查询的另一方法是创建计算字段。假如需要显示customers 表中每个客户的订单总数。订单与相应的客户ID存储在orders表中。 为了执行这个操作,遵循下面的步骤。

(1) 从customers表中检索客户列表。

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

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

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

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

这条 SELECT 语句对 customers 表中每个客户返回 3 列 : cust_name、cust_state和orders。orders是一个计算字段, 它是由圆括号中的子查询建立的。该子查询对检索出的每个客户执行一 次。在此例子中,该子查询执行了5次,因为检索出了5个客户。 子查询中的WHERE子句与前面使用的WHERE子句稍有不同,因为它使用了完全限定列名。下面的语句告诉SQL比较 orders表中的cust_id与当前正从customers表中检索的cust_id:

WHERE orders.cust_id = customers.cust_id

这种类型的子查询称为相关子查询。任何时候只要列名可能有多义性,就必须使用这种语法(表名和列名由一个句点分隔)。

用子查询测试和调试查询很有技巧性,特别是在这些语句的复杂性不断增加的情况下更是如此。用子查询建立(和测试)查询的最可靠的方法是逐渐进行, 这与MySQL处理它们的方法非常相同。首先,建立和测试最内层的查询。然后,用硬编码数据建立和测试外层查询,并且仅在确认它正常后才嵌入子查询。这时,再次测试它。对于要增加的每个查询,重复这些步骤。这样做仅给构造查询增加了 一点点时间,但节省了以后(找出查询为什么不正常)的大量时间,并且极大地提高了查询一开始就正常工作的可能性。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值