使用表列名

  • 别名除了用于列名和计算字段外,SQL还允许给表名起别名。

    这有两个理由:

    1. 缩短SQL语句;
    2. 允许在单条SELECT语句中多次使用相同的表。
1
2
3
4
5
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';
  • 表别名不仅能用于WHERE子句,它还可以用于SELECT的列表、ORDER BY子句以及语句的其他部分。
  • 表别名只在查询执行中使用。
  • 与列别名不一样,表别名不返回到客户机。

使用不同类型的联结

  • 除了内部联结或称等值联结的简单联结,现介绍3种其他联结,分别为自联结、自然联结和外部联结。

自联结

1
2
3
4
5
6
7
8
9
10
11
-- 找出生产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 AS p1, products AS p2
WHERE p1.vend_id = p2.vend_id
AND p2.prod_id = 'DTNTR';
  • 用自联结而不是子查询:自联结通常作为外部语句用来替代从相同表中检索数据时使用的子查询语句。

    虽然最终的结果是相同的,但有时候处理联结远比处理子查询快得多。应该试一下两种方法,以确定哪一种的性能更好。

自然联结

  • 标准的联结:返回所有数据,甚至相同的列多次出现。

  • 自然联结:排除多次出现,使每个列只返回一次。

  • 自然联结是这样一种联结,其中你只能选择那些唯一的列。

    这一般是通过对表使用通配符(SELECT *),对所有其他表的列使用明确的子集来完成的。

1
2
3
4
5
6
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';

外部联结

1
2
3
4
5
6
7
8
9
-- 内部联结。检索所有客户,包括其订单。
SELECT customers.cust_id, orders.order_num
FROM customers INNER JOIN orders
ON customers.cust_id = orders.cust_id;

-- 外部联结。检索所有客户,包括没有订单的客户。
SELECT customers.cust_id, orders.order_num
FROM customers LEFT OUTER JOIN orders
ON customers.cust_id = orders.cust_id;
  • 没有*=操作符:MySQL不支持简化字符*==*的使用,这两种操作符再其他DBMS中是很流行的。

  • 外部联结的类型:存在两种基本的外部联结形式:左外部联结和右外部联结。

    他们之间唯一的差别是所关联的表的顺序不同。

    左外部联结可以通过颠倒FROMWHERE子句中表的顺序转换为右外部联结。使用哪一种纯属看心情了。

使用带聚集函数的联结

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
-- 检索所有客户及每个客户所下的订单数
SELECT customers.cust_name,
customers.cust_id,
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_name,
customers.cust_id,
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;

使用联结和联结条件

  • 注意所使用的联结类型。一般我们使用内部联结,但是用外部联结也是有效的。

  • 保证使用正确的联结条件,否则将返回不正确的数据。

  • 应该总是提供联结条件,否则会得出笛卡尔积。

  • 在一个联结中可以包含多个表,甚至对于每个联结可以采用不同的联结类型。

    虽然这样做是合法的,一般也很有用,但应该在一起测试他们前,分别测试每个联结。这将使故障排除更为简单。