学习目的:
了解另外一些联结类型,包括它们的含义和使用方法,如何对被联结的表使用别名和聚集函数。
使用表别名:
别名除了用于列名和计算字段外,SQL还允许给表名起别名。这样做主要有两个理由:
- 缩短SQL语句
- 允许在单个SELECT语句中多次使用相同的表
Q: 对表使用别名
SELECT cust_name, cust_contact
FROM customers AS c, orders AS o, orderitems AS oi
WHERE c.cust_id = o.cust_id
AND oi.order_num = o. order_num
AND prod_id = 'TNT2';
应该注意,表别名只在查询执行中使用。与列别名不一样,表别名不返回客户机。
使用不同类型的联结:
自联结:
字联结通常作为外部语句来替代从相同表中检索数据时使用的子查询语句。虽然最终的结果是相同的,但有时候处理联结远比处理子查询要快的多。
Q找出供应商(其ID为DTNTR,这里的ID为prod_id )生产的其他物品。
问题分析:
(1)找出prod_id = 'DTNTR'的vend_id products表
(2)通过vend_id 找到其生产的其他产品。vendoes表
##用子查询的方式
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 AS p1, products AS p2
WHERE p1.vend_id = p2.vend_id
AND p2.prod_id = 'DTNTR';
自然联结:
无论何时对表进行联结,应该至少有一个列出现在不知一个表中(被联结的列)。标准的联结(前一章介绍的内部联结)返回所有数据,甚至相同的列多次出现。自然联结排除多次出现,使每个列只返回一次。
自然联结是这样一种联结,其中你只能选择那些唯一的列。这一般是通过对表使用通配符(SELECT *),对所有其他表的列使用明确的子集来完成的。
#自热联结(不太明白)返回产品ID为FB的客户信息和订单信息。
SELECT c.*, o.order_num, o.order_date, oi.prod_id, oi.quantity, oi.item_price
FROM customers AS c, orders AS o, orderitems AS oi
WHERE c.cust_id = o.cust_id
AND oi.order_num = o.order_num
AND prod_id = 'FB';
外部联结:
许多联结将一个表中的行与另一个表中的行相关联。但有时候会需要包含没有关联行的那些行。例如,可能需要使用联结来完成以下工作:
- 对每个客户下了多少订单进行计数,包括那些至今尚未下订单的客户;
- 列出所有产品以及订购数量,包括没有人订购的产品;
- 计算平均销售规模,包括那些至今尚未下订单的客户。
在上述例子中,联结包含了那些在相关表中没有关联行的行。这种类型的联结称为外部联结。
Q:检索所有客户,包括那些没有订单的客户。
SELECT customers.cust_id, orders.order_num
FROM customers LEFT OUTER JOIN orders
ON customers.cust_id = orders.cust_id;
在使用OUTER JOIN语法时,必须使用RIGHT 或LEFT关键字,指定包括其所有行的表(RIGHT 指出的是OUTER JOIN 右边的表,而LEFT指定的是OUTER JOIN左边的表)
没有*=操作符,MySQL不支持简化字符*=和=*的使用,这两种操作符在其他DBMS中是很流行的。
使用带聚集函数的联结:
Q: 检索所有客户及每个客户所下的订单。
SELECT customers.cust_id,customers.cust_name,COUNT(orders.order_num) AS num_ord
FROM customers INNER JOIN orders
ON customers.cust_id = orders.cust_id
GROUP BY customers.cust_id;
##检索出所有客户,甚至是没有下订单的客户。
SELECT customers.cust_id,customers.cust_name,COUNT(orders.order_num) AS num_ord
FROM customers LEFT OUTER JOIN orders
ON customers.cust_id = orders.cust_id
GROUP BY customers.cust_id;
使用联结和联结条件:
- 注意使用的联结类型。一般我们使用内部联结,但使用外部联结也是有效的。
- 保证使用正确的联结条件,否则将返回不正确的数据。
- 应该总是提供联结条件,否则得出笛卡尔积。
- 在一个联结中可以包含多个表,甚至对于每个联结可以采用不同的联结类型。虽然这样做是合法的,一般也很有用,但应该在一起测试它们前,分别测试每个联结。这样做将使故障排除更为简单。