Mysql的子查询其实就是Select语句的嵌套,用于从多个表格检索数据的情况。
检索订购了TNT2这个商品的所有客户的信息(客户的姓名,联系方式等),通过对数据库的了解,发现这里给定的条件和检索的结果不在同一张表里面而是分在两个表里面,因此单一查询做不到。我们需要通过找到这两个表的关系。发现,这两个表可以通过orders表联系起来。
mysql> DESCRIBE orderitems;
+------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------+------+-----+---------+-------+
| order_num | int(11) | NO | PRI | NULL | |
| order_item | int(11) | NO | PRI | NULL | |
| prod_id | char(10) | NO | MUL | NULL | |
| quantity | int(11) | NO | | NULL | |
| item_price | decimal(8,2) | NO | | NULL | |
+------------+--------------+------+-----+---------+-------+
5 rows in set (0.76 sec)
mysql> DESCRIBE orders;
+------------+----------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+----------+------+-----+---------+----------------+
| order_num | int(11) | NO | PRI | NULL | auto_increment |
| order_date | datetime | NO | | NULL | |
| cust_id | int(11) | NO | MUL | NULL | |
+------------+----------+------+-----+---------+----------------+
3 rows in set (0.13 sec)
mysql> DESCRIBE customers;
+--------------+-----------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+-----------+------+-----+---------+----------------+
| cust_id | int(11) | NO | PRI | NULL | auto_increment |
| cust_name | char(50) | NO | | NULL | |
| cust_address | char(50) | YES | | NULL | |
| cust_city | char(50) | YES | | NULL | |
| cust_state | char(5) | YES | | NULL | |
| cust_zip | char(10) | YES | | NULL | |
| cust_country | char(50) | YES | | NULL | |
| cust_contact | char(50) | YES | | NULL | |
| cust_email | char(255) | YES | | NULL | |
+--------------+-----------+------+-----+---------+----------------+
9 rows in set (0.09 sec)
通过研究上面表结构,得出思路:
1、检索包含TNT2的订单号,在orderitems表中 SELECT order_num FROM orderitems WHERE prod_id='TNT2';
2、根据订单号查找到客户ID,在orders表中 SELECT cust_id FROM orders WHERE order_num IN (20005,20007);
3、根据客户ID查找到客户的姓名和联系方式,在customers表中 SELECT cust_name,cust_contact FROM customers WHERE cust_id IN (10001,10004);
子查询方法:
就是讲上面三条SELECT语句合并到一个SELECT语句中:
mysql> 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'));
结果是:
+----------------+--------------+
| cust_name | cust_contact |
+----------------+--------------+
| Coyote Inc. | Y Lee |
| Yosemite Place | Y Sam |
+----------------+--------------+
2 rows in set (0.01 sec)
上面的例子是在WHERE子句里面使用SELECT语句。
还有一种情况是在SELECT语句里面使用SELECT语句。
看下面这个例子:
检索customers表中,每个客户的订单数量。
分析,客户的信息存放在customers表中,客户的订单是存放到orders表中里面的。两个订单是通过cust_id关联起来的。
算出每个客户的订单ID行数,就能得知他的订单数量。
mysql> SELECT cust_name,(SELECT COUNT(*) FROM orders WHERE orders.cust_id=customers.cust_id) AS orders FROM customers ORDER BY cust_name;
结果是:
+----------------+--------+
| cust_name | orders |
+----------------+--------+
| Coyote Inc. | 2 |
| E Fudd | 1 |
| Mouse House | 0 |
| Wascals | 1 |
| Yosemite Place | 1 |
+----------------+--------+
5 rows in set (0.07 sec)
用子查询建立查询的最可靠的方法是逐渐进行。
首先,建立最内层查询,然后用硬编码的数据建立外层查询,并且仅在确认它正常后才嵌入子查询。这时,再次测试它,对于要增加的每个子查询,重复这些步骤。