1.使用表别名
给列起别名的语法如下(第7章),输入:
SELECT Concat(vend_name, ' (', RTRIM(vend_country), ')')
FROM Vendors
ORDER BY vend_name;
输出:
SQL除了可以对列名和计算字段使用别名,还允许给表名起别名。理由是:
缩短SQL语句;
允许在一条SELECT语句中多次使用相同的表。
对前一课的例子:
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= 'RGAN01';
改为使用别名,输入:
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= 'RGAN01';
输出:
此例中表别名值用于WHERE子句,其实还可以用于SELECT的列表、ORDER BY子句以及其他语句部分。表别名只在查询执行中使用,不返回到客户端。
2.使用不同类型的联结
除了内联结或等值联结的简单联结,有三种其他联结:自联结(self_join)、自然联结(natural join)和外联结(outer join)。
(1)自联结
假设要给与Jim Jones同一公司的所有顾客发送一封信件,该查询要求首先找出Jim Jones所在公司,然后找出在该公司的所有顾客。
第一种解决方案,使用子查询,输入:
SELECT cust_id, cust_name, cust_contact
FROM Customers
WHERE cust_name = (SELECT cust_name
FROM Customers
WHERE cust_contact = 'Jim Jones');
输出:
第二中解决方案,使用联结,输入:
SELECT c1.cust_id, c1.cust_name, c1.cust_contact
FROM Customers AS c1, Customers as c2
WHERE c1.cust_name = c2.cust_name
AND c2.cust_contact = 'Jim Jones';
输出:
此查询中需要的两个表实际是相同的,因此Customers表在FROM子句中出现了两次,对Customers的引用具有歧义性,因为DBMS不知道引用的是哪个Customers表。表别名可以解决该问题。注意,SELECT语句使用c1前缀明确给出所需列的全面,否则,DBMS将返回错误。
(2)自然联结
标准联结(内联结)返回所有的数据,相同的列甚至多次出现,而自然联结排除多次出现,使每一列只返回一次。
自然联结要求只能选择那些唯一的列,一般通过对一个表使用通配符(SELECT(*)),而对于其他表的列使用明确的子集来完成。
输入:
SELECT C.*, O.order_num, O.order_date
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= 'RGAN01';
输出:
列出了订购物品'RGAN01'的所有顾客及其信息。
此列中,通配符只对第一个表使用,所有其他列明确列出。所以没有重复的列被检索出来。
(3)外联结
外联结包含了那些在相关表中没有关联行的行,例如:
1)对每个顾客下的订单进行计数,包括哪些至今尚未下订单的顾客;
2)列出所有产品以及订购数量,包括没有人订购的产品;
3)计算平均销售规模,包括哪些至今尚未下订单的顾客。
下面是一个简单的内联结,检索所有顾客及其订单,输入:
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;
输出:
此SQL语句使用了关键字OUTER JOIN来指定连接类型,而不是在WHERE子句中指定。但必须用LEFT或RIGHT关键字指定包括其所有行的表,RIGHT指的是OUTER JOIN右边的表,LEFT指的是左边的表。
为了从右边的表选择所有行,输入:
SELECT Customers.cust_id, Orders.order_num
FROM Customers RIGHT OUTER JOIN Orders
ON Customers.cust_id = Orders.cust_id;
输出:
另一种外联结——全外联结(full outer join),它检索两个表中的所有行并关联那些可以关联的行。全外联结包含两个表的不关联行。语法如下。
输入:
SELECT Customers.cust_id, Orders.order_num
FROM Customers FULL OUTER JOIN Orders
ON Customers.cust_id = Orders.cust_id;
输出:MySQL不支持FULL OUTER JOIN语法。
3.使用带聚集函数的联结
聚集函数除了从一个表汇总数据,也可以与联结一起使用。
假设要检索所有顾客即每个顾客下的订单数,使用COUNT()函数来完成,输入:
SELECT 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语句使用INNER JOIN将Customers和Orders表互相关联,GROUP BY子句按顾客分组分组数据,因此函数调用Count(Orders.order_num)对内个顾客的订单技术,将其作为num_ord返回。
聚集函数也可以与其他联结一起使用,输入:
SELECT 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;
输出:
使用左外部联结来包含所有顾客,甚至那些没有任何订单的顾客。如1000000002顾客,他有0个订单。
4.使用联结和联结条件
(1)注意所使用的联结类型,一般使用内联结,但使用外联结也有效。
(2)应该查看具体文档获得确切的联结语法。
(3)保证使用正确的联结语法,否则会返回不正确的数据。
(4)应该总是提供联结条件,否则会得出笛卡尔积。
(5)在一个联结中可以包含多个表,甚至可以对每个联结采用不同的联结类型,但是应该在一起测试它们之前分别测试每个联结。