MySQL必知必会 摘录(3)
14.3 作为计算字段使用子查询
使用子查询的另一方法是创建计算字段。假如需要显示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 cust_name, cust_state,
(SELECT COUNT(*)
FROM orders
WHERE orders.`cust_id` = customers.cust_id) AS orders
FROM customers
ORDER BY cust_name;
这 条 SELECT 语句对 customers 表中每个客户返回 3 列 :cust_name、cust_state和orders。orders是一个计算字段,它是由圆括号中的子查询建立的。该子查询对检索出的每个客户执行一次。在此例子中,该子查询执行了5次,因为检索出了5个客户。
这种类型的子查询称为 相关子查询。
逐渐增加子查询来建立查询
用子查询测试和调试查询很有技巧性,特别是在这些语句的复杂性不断增加的情况下更是如此。用子查询建立(和测试)查询的最可靠的方法是逐渐进行,这与MySQL处理它们的方法非常相同。首先,建立和测试最内层的查询。然后,用硬编码数据建立和测试外层查询,并且仅在确认它正常后才嵌入子查询。这时,再次测试它。对于要增加的每个查询,重复这些步骤。这样做仅给构造查询增加了一点点时间,但节省了以后(找出查询为什么不正常)的大量时间,并且极大地提高了查询一开始就正常工作的可能性。
16.2.1 自联结
假如你发现某物品(其ID为DTNTR)存在问题,因此想知道生产该物品的供应商生产的其他物品是否也存在这些问题。此查询要求首先找到生产ID为DTNTR的物品的供应商,然后找出这个供应商生产的其他物品。下面是解决此问题的一种方法:
SELECT prod_id, prod_name
FROM products
WHERE vend_id = (SELECT vend_id
FROM products
WHERE prod_id = 'DTNTR');
这是第一种解决方案,它使用了子查询。
现在来看使用 自联结的相同查询:
SELECT p1.prod_id, p1.prod_name
FROM products p1
JOIN products p2
ON p1.vend_id = p2.vend_id
WHERE p2.prod_id = 'DTNTR';
用自联结而不用子查询
自联结通常作为外部语句用来替代从相同表中检索数据时使用的子查询语句。
虽然最终的结果是相同的,但有时候处理联结远比处理子查询快得多。
应该试一下两种方法,以确定哪一种的性能更好。

浙公网安备 33010602011771号