第十四章使用子查询
14.1子查询
迄今为止所有的SELECT语句都是简单查询,即从单个数据库表中检索的单条语句。查询一般是指SELECT语句。
14.2利用子查询进行过滤
输入:
SELECT order_num
FROM orderitems
WHERE prod_id = 'TNT2';
输出:
说明:包含TNT2商品的订单分别为20005和20007。
输入:
SELECT cust_id
FROM orders
WHERE order_num IN (20005,20007);
输出:
说明:知道了20005和20007订单中包含有TNT2的商品,那么就可以利用这两个订单编号在orders表中查到这两个订单对应的客户号。
输入:
SELECT cust_id
FROM orders
WHERE order_num IN (SELECT order_num
FROM orderitems
WHERE prod_id = 'TNT2');
输出:
说明:这种写法是上面的合并,将第一次查询得到的结果作为第二次查询的过滤条件,即可以把一条SELECT语句的返回结果用于另一条SELECT语句的WHERE子句。子查询是从内到外将进行处理的,即先处理根据商品号查找订单号的查询,再进行根据订单号查询客户号的操作。
输入:
SELECT cust_name, cust_contact
FROM customers
WHERE cust_id IN (10001,10004);
输出:
说明:在上一步的查询中得到了订购TNT2商品的客户ID,那么就可以利用客户ID在customers表中检索出客户的其他信息。
输入:
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'));
输出:
说明:1.这三个SELECT语句仍然可以叠加,第一次的查询是第二次的过滤条件,两者嵌套而成的查询又是第三次查询的过滤条件。
2.在使用子查询时,列必须匹配,即WHERE子句中的列的数目必须与嵌套的子查询中列的数目一致。
14.3作为计算字段使用子查询
使用子查询的另一方式是创建计算字段。
需求:显示customers表中每个客户的订单总数。
分解:如果是查询某个客户的订单总数,可以在orders表中使用cust_id进行过滤,使用COUNT计数得到。
输入:
SELECT COUNT(*) AS orders
FROM orders
WHERE cust_id = 10001;
输出:
为了对每一个客户执行COUNT(*)操作,那么COUNT(*)可以作为一个子查询。
输入:
SELECT cust_name,
cust_state,
(SELECT COUNT(*) AS orders
FROM orders
WHERE orders.cust_id = customers.cust_id) AS orders
FROM customers
ORDER BY cust_name;
输出:
说明:这里的子查询是对每个客户都使用了一次。这种子查询被称为相关子查询,即涉及外部的子查询。在相关子查询中对列名进行了完全限定,如果不进行完全限定,会出现如下所示的情况。
输入:
SELECT cust_name,
cust_state,
(SELECT COUNT(*) AS orders
FROM orders
WHERE cust_id = cust_id) AS orders
FROM customers
ORDER BY cust_name;
输出:
说明:在不完全限定列名时,子查询中实际上进行的过滤是orders表中的cust_id列的自身比较,返回的也总是orders表中的订单总数。
注意:用子查询建立(和测试)查询的最可靠的方法是逐渐进行,这与MySQL处理它们的方法非常相同。首先,建立和测试最内层的查询。然后,用硬编码数据建立和测试外层查询,并且仅在确认它正常后才嵌入子查询。这时,再次测试它。对于要增加的每个查询,重复这些步骤。