Sams Teach Yourself SQL in 10 Minutes(Fourth Edition)学习记录

第13课 创建先进的连接(Creating Advanced Joins)

本课学习其他的连接类型-他们是什么?如何使用他们?也会学习如何呢使用表别名和如何使用带连接表的聚合函数。

13.1 使用表别名(Using Table Aliases)

第七课,创建计算字段中,已经学了如何使用别名来查询获取表列。别名某个列的句法如下:

输入:

SELECT RTRIM(vend_name) + ' (' + RTRIM(vend_country) +

')'

AS vend_title
FROM Vendors
ORDER BY vend_name;

除了使用列名别名和计算字段别名,SQL也使你能够别名表名。这样做有两个主要原因:
1、缩短SQL句法;
2、使能在一个单个SELECT声明中,多重使用相同的表 。

看下面SELECT声明。基本上与前面课程中学习的例子申明相同,但这里已经修改为使用别名:

输入:

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';

分析:
注意啊到FROM语句中三个表都使用了别名(aliase)。Customers AS C建立C作为Customers的别名,诸如此类。这使你使用缩写的C替换全文本Customers。在这个例子中,别名表仅用在WHERE语句中,但是别名不限于仅仅在WHERE语句中。你可以在SELECT列表中使用别名,在ORDER BY语句中,以及在声明的任何其他部分中使用别名。

Caution: No AS in Oracle

Oracle不支持AS关键字。在Oracle中使用别名仅仅指定别名不带AS(所以Customers C代替Customers AS C).

值得注意的是,表别名仅在查询执行过程中起作用。不像列别名,表别名从不返回给客户端。

13.2 使用不同的连接类型(Using Different Join Types)

截止目前,你仅仅使用简单的连接称为内部连接或者同等连接(equijoins)。现在要看三个额外的连接类型:自连接(the self join),自然连接(the natural join)以及外部连接(the outer join)。

13.2.1 Self Joins(自连接)

我早前提过,使用表别名的一个主要原因是在一个单个SELECT声明中,能够查询相同的表多于一次。一个例子会证明这个。

假如你想要发送一封邮件给所有与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');

输出:
cust_id cust_name cust_contact


1000000003 Fun4All Jim Jones
1000000004 Fun4All Denise L. Stephens

分析:
第一个解决方案使用了子查询。内部SELECT声明做了一个简单的查询来返回Jim Jones工作的公司的cust_name。那个名字是外部查询在WHERE语句中的使用的名字,这样所有为这家公司工作的员工的名字都查询到了。

下面使用一个连接来看相同的查询:

输入:

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';

输出:
cust_id cust_name cust_contact


1000000003 Fun4All Jim Jones
1000000004 Fun4All Denise L. Stephens

Tip: No AS in Oracle

Oracle用户,记得去掉AS。

分析:
这个查询中需要的两个表实际上是相同的。所以Customers表在FROM语句中出现两次。尽管这完全合法,任何提及表Custormers会模糊不清,因为DBMS不知道你提到哪个Customers表。

为解决这个问题,使用了表别名。首次出现的Customers有一个别名C1,第二次出现的Customers别名为C2。现在这些别名可以用做表的名字。例如,SELECT声明使用C1前缀来明确声明期望的列(desired columns)的全名。如果没有这样做,DBMS会返回错误,因为这样的有两个,其中每列名称为cust_id、cust_name和cust_contact。无法知道哪个是你想要的(即使他们相同)。WHERE语句首先连接表,接着通过第二个表中的cust_contact过滤数据,仅仅返回想要的数据。

Tip:自连接代替子查询

自连接经常用于代替声明,这些声明是通过使用子查询来从相同表中取出数据作为外部声明的。尽管最终结果是相同的,许多DBMS处理连接(joins)远远快于处理子查询(subqueries)。这两种方式都值得做试验以确定哪个更好。

13.2.2 自然连接(Natural Joins)

每当表连接,至少一列将出现在多于一张表中(这些列用于创建连接)。标准连接(前一课学习的内部连接)返回所有数据,甚至相同列多次出现。自然连接简单地消除那些多次出现以便每列中仅仅一个返回。

它是怎么做到这样的?答案是它做不到-你做到的。自然连接是一个连接,在这个连接中你仅选择唯一的列。这是典型的做法,针对一个表使用一个通配符(SELECT *),针对所有其他表使用明确子组。

下面例子:
输入:

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 = 'RGAN01';

Tip: No AS in Oracle

Oracle用户,记得去掉AS。

分析:
本例中,通配符仅用于第一张表。明确列出所有其他的列,这样不会返回重复的列。

事实情况是,到目前为止,你创建的每个内部连接,实际上是自然连接,你将可能从不需要不是自然连接的内部连接 。

13.2.3 外部连接(Outer Joins)

多数连接关联一张表中的行与另一张表中的行。但是经常,你想要包含那些没有关联的行。例如,你可能使用连接来完成下面的任务:
1、计算每个客户下了多少订单,包括那些已经下单的客户。
2、根据订单数量列出所有产品,包括产品不是俺任何人排序的。
3、计算平均销售规模,将那些还没有下单的客户也考虑进去。

在这些例子中,包含表行的连接在关联表中没有关联行。这种连接类型称为外部连接。

Caution:句法差异

It is important to note that the syntax used to create an outer join can vary slightly among different SQL implementations. The various forms of syntax described in the following section cover most
implementations, but refer to your DBMS documentation to verify its syntax before proceeding.

下面的SELECT声明是一个简单的内部连接。它找回所有客户及其订单的列表:
输入:

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;

输出:
cust_id order_num


1000000001 20005
1000000001 20009
1000000002 NULL
1000000003 20006
1000000004 20007
1000000005 20008

分析:
正如上一课中见过的内部连接,这个SELECT声明使用关键字OUTER JOIN来指定连接类型(取代在WHERE语句中指定的)。但是不像内部连接,关联两张表中的行,外部连接也包含没有关系的行。当使用OUTER JOIN语法,你必须使用RIGHT或者LEFT关键字来指定表,该表包含所有行。(RIGHT for the one on the right of OUTER JOIN, and LEFT for the one on the left).前面的例子使用LEFT OUTER JOIN来从左边的FROM语句中选择所有的行 (Custormers表)。为从右边表中选择所有的行,使用RIGHT OUTER JOIN,正如下个例子所见的:

输入:

SELECT Customers.cust_id, Orders.order_num
FROM Customers RIGHT OUTER JOIN Orders
ON Orders.cust_id = Customers.cust_id;

Caution: SQLite Outer Joins

SQLite支持LEFT OUT JOIN,但不支持RIGHT OUTER JOIN。Fortunately, if you do need RIGHT OUTER JOIN functionality in SQLite, there is a very simple solution as will be explained in the next tip.

Tip:外部连接类型

Remember that there are always two basic forms of outer joins—the left outer join and the right outer join. The only difference between them is the order of the tables that they are relating. In other words, a left outer join can be turned into a right outer join simply by reversing the order of the tables in the FROM or WHERE clause. As such, the two types of outer join can be used interchangeably, and the decision about which one is used is based purely on convenience.

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容