⚠️版本要求:MySQL4.1引入了对子查询的支持,所以要想使用本章描述的mysql必须使用4.1更高的版本。
例:列出订购物品TNT2的所有客户的客户信息。
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') );
复制代码
虽然子查询一般与IN操作符结合使用,但也可以用于测试等于(=),不等于(<>)
例:显示customers表中每个客户的订单总数
SELECT cust_name,
cust_state,
(SELECT COUNT(*)
FROM orders
WHERE orders.cust_id = customers.cust_id) AS orders
FROM customers
ORDER BY cust_name;
复制代码
SQL强大的功能之一就是可以在数据检索查询的执行中联结。
我们设计两个表,一个供应商表,一个商品表,供应商表的主键标识就是商品表的外键。
这样关系数据可以有效的存储和方便的处理,他的可伸缩性是要远远好于非关系数据库。
可伸缩性
能够不断适应增加的工作量而不失败,设计良好的数据库或应用程序称之为可伸缩性好。
就像上面说的,你把数据分解到多个数据表这是有代价的,如果你想要的数据在多个数据表中你要怎么办呢?
答案就是使用联结。
SELECT vend_name ,prod_name,prod_price
FROM vendors,products
WHERE vendors.vend_id = products.vend_id
ORDER BY vend_name,prod_name;
复制代码
这里要完全限定列名,不然MySQL可处理不了这种充满二义性的WHERE语句。
在联结两个表的时候。实际是将第一个表的每一行,与第二个表的每一行配对,WHERE子句作为过滤条件,他只包含哪些匹配给定条件的行。没有WHERE子句,返回的信息将是特别特别多的呀。
笛卡尔积
由于没有连接条件的表关系返回的结果为笛卡尔积。检索出的行的数目
目前为止的所有连接都是等值连接,他是基于两个表之间的相等测试。这种连接称为内部联结。其实,这种连接是原有另外一种写法 的。(这种写法可以明确指定连接的类型)
SELECT vend_name ,prod_name ,prod_price
FROM vendors INNER JOIN products
ON vendors.vend_id = products.vend_id;
复制代码
SELECT prod_name ,vend_name ,prod_price ,quantity
FROM orderitems ,products, vendors
WHERE products.vend_id = vendors.vend_id
AND orderitems.prod_id = products.prod_id
AND order_num = 20005;
复制代码
mysql处理联结表是特别浪费性能的,所以我们要仔细,不要联结不必要的表。联结的表越多,性能的下降越厉害。
我们可以把之前的一个SELECT拿出来搞一个一题多解。
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') );
复制代码
我们试试联结的方法
SELECT cust_name , cust_contact
FROM customers , orders, orderitems
WHERE customers.cust_id = orders.cust_id
AND orderitems.order_num = orders.order_num
AND prod_id = 'TNT2';
复制代码