美文网首页
《SQL必知必会》笔记7-高级联结(as、self-join、o

《SQL必知必会》笔记7-高级联结(as、self-join、o

作者: hufengreborn | 来源:发表于2017-07-23 15:25 被阅读0次

1 创建高级联结(别名、自联结、外联结)

1.1 使用表别名AS

使用别名的两个主要理由:

  • 缩短SQL语句。
  • 允许在一条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';

别名不仅能用于WHERE子句,还可以用于SELECT列表、ORDER BY子句以及其他语句部分。


1.2 使用不同类型的联结

除了内联结INNER JOIN之外,还有三种其他联结方式:自联结(self-join)、自然联结(natural join)和外联结(outer join)。


1.2.1 自联结self-join

自联结指的是要检索的两个表实际上是同一个表。

假如要给与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';

一般来说,许多DBMS处理联结远比处理子查询快得多。


1.2.2 自然联结natural join

在对表进行联结时,至少有一列(被联结的列)不止出现在一个表中。标准的内联结返回所有数据,相同的列甚至多次出现。自然联结排除多次出现,使每一列只返回一次。

自然联结要求只能选择那些唯一的列,一般通过对一个表使用通配符(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';

在这个例子中,通配符只对第一个表使用。所有其他列明确列出,所以没有重复的列被检索出来。

事实上,我们迄今为止建立的每个内联结都是自然联结,很可能永远都不会用到不是自然联结的内联结。


1.2.3 外联结outer join

许多联结将一个表中的行与另一个表中的行相关联,但有时候需要包含没有关联的那些行。

例如:

  • 对每个顾客下的订单进行计数,包括哪些至今尚未下订单的顾客。
  • 列出所有产品以及订购数量,包括没有人订购的产品。
  • 计算平均销售规模,包括哪些至今尚未下订单的顾客。

在上述例子中,联结包含了那些在相关表中没有关联行的行,这种联结称为外联结(outer join)。

内联结检索所有顾客及其订单:

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;

使用OUTER JOIN语法时,必须使用RIGHT或LEFT关键字指定包括其所有行的表(RIGHT指出的是OUTER JOIN右边的表,而LEFT指出的是OUTER JOIN左边的表)。

上面的例子使用LEFT OUTER JOIN从FROM子句左边的表(Customers表)中选择所有行。为了从右边的表中选择所有行,需要使用RIGHT OUTER JOIN,如下例所示。

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

还存在另一种外联结,就是全外联结(full outer join),它检索两个表中的所有行并关联那些可以关联的行,全外联结包含了两个表中的不关联的行。(Access、MariaDB、MySQL和SQLite不支持FULL OUTER JOIN语法)

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

1.3 使用带聚集函数的联结

检索所有顾客及每个顾客所下的订单数:

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

1.4 使用联结和联结条件

  1. 注意所使用的联结类型。一般我们使用内联结,但使用外联结也有效。
  2. 保证使用正确的联结条件,否则会返回不正确的数据。
  3. 应该总是提供联结条件,否则会得出笛卡尔积。
  4. 在一个联结中可以包含多个表,甚至可以对每个联结采用不同的联结类型。虽然这样做是合法的,一般也很有用,但应该在一起测试它们前分别测试每个联结,这会使故障排除更为简单。

2 组合查询(UNION)

2.1 组合查询

多数SQL查询只包含从一个或多个表中返回数据的单条SELECT语句,但是SQL也允许执行多个查询(多条SELECT语句),并将结果作为一个查询结果集返回。这些组合查询通常称为并(union)或复合查询(compound query)。

使用组合查询的两个主要情况:

  1. 在一个查询中从不同的表返回结构数据。
  2. 对一个表执行多个查询,按一个查询返回数据。

2.2 创建组合查询

可用UNION操作符来组合数条SQL查询,利用UNION,可给出多条SELECT语句,将它们的结果组合成一个结果集。


2.2.1 使用UNION

给出每条SELECT语句,在各条语句之间放上关键字UNION。

例如,需要Illinois、Indiana和Michigan等美国几个州的所有顾客的报表,还想包括不管位于哪个州的所有的Fun4All。当然可以利用WHERE子句来完成此工作,不过这次我们使用UNION。

使用WHERE语句:

SELECT cust_name, cust_contact, cust_email
FROM Customers
WHERE cust_state IN ('IL','IN','MI')
OR cust_name = 'Fun4All';

使用UNION语句:

SELECT cust_name, cust_contact, cust_email
FROM Customers
WHERE cust_state IN ('IL','IN','MI')
UNION
SELECT cust_name, cust_contact, cust_email
FROM Customers
WHERE cust_name = 'Fun4All';

在这个简单的例子中,使用UNION可能比使用WHERE子句更为复杂。但对于较复杂的过滤条件,或者从多个表(而不是一个表)中检索数据的情形,使用UNION可能会使处理更简单。


2.2.2 UNION规则

  1. UNION必须由两条或两条以上的SELECT语句组成,语句之间用关键字UNION分隔。如果组合四条SELECT语句,将要使用三个UNION关键字。
  2. UNION中的每个查询必须包含相同的列、表达式或聚集函数,各个列不需要以相同的次序列出。
  3. 列数据类型必须兼容:类型不必完全相同,但必须是DBMS可以隐含转换的类型(例如,不同的数值类型或不同的日期类型)。

2.2.3 包含或取消重复的行

UNION从查询结果集中自动去除了重复的行,它的行为与一条SELECT语句中使用多个WHERE子句条件一样。使用UNION时,重复的行会自动取消。

如果想返回所有的匹配行,可使用UNION ALL而不是UNION。

SELECT cust_name, cust_contact, cust_email
FROM Customers
WHERE cust_state IN ('IL','IN','MI')
UNION ALL
SELECT cust_name, cust_contact, cust_email
FROM Customers
WHERE cust_name = 'Fun4All';

2.2.4 对组合查询结果排序

在用UNION组合查询时,只能使用一条ORDER BY子句,它必须位于最后一条SELECT语句之后。

对于结果集,不存在用一种方式排序一部分,而又用另一种方式排序另一部分的情况,因此不允许使用多条ORDER BY子句。

SELECT cust_name, cust_contact, cust_email
FROM Customers
WHERE cust_state IN ('IL','IN','MI')
UNION
SELECT cust_name, cust_contact, cust_email
FROM Customers
WHERE cust_name = 'Fun4All'
ORDER BY cust_name, cust_contact;

虽然ORDER BY子句似乎只有最后一条SELECT语句的组成部分,但实际上DBMS将用它来排序所有SELECT语句返回的所有结果。


如果您发现文中有不清楚或者有问题的地方,请在下方评论区留言,我会根据您的评论,更新文中相关内容,谢谢!

相关文章

  • 《SQL必知必会》笔记7-高级联结(as、self-join、o

    1 创建高级联结(别名、自联结、外联结) 1.1 使用表别名AS 使用别名的两个主要理由: 缩短SQL语句。 允许...

  • SQL必知必会学习笔记3

    SQL必知必会学习笔记3 十三、创建高级联结 1.使用表别名 警告: Oracle中没有AS,直接指定Custom...

  • 高性能 SQL 计划 Day 3

    今天继续来学 SQL,主要是《MySQL必知必会》15-18章的内容。 Ch 15.联结表 1.联结 SQL 最强...

  • SQL 学习笔记

    SQL基础 参考书籍: 《SQL必知必会》 检索数据 过滤数据 函数 分组数据 子查询 简单联结 法一: 法二: ...

  • 03随风而逝

    写写今天学到的知识, 简单,少。 《mysql必知必会》:有 子查询,联结表,高级联结,组合查询,插入数据,更新和...

  • mysql必知必会

    title: mysql必知必会date: 2019-11-21tags: 笔记categories: sql ...

  • SQL必知必会

    《SQL必知必会》SQL是使用 广泛的数据库语言,几乎所有重要的DBMS都支持SQL。《SQL必知必会(第4版)》...

  • SQL 基础笔记

    本文为 SQL必知必会 的读后笔记 SELECT 语句 多条SQL语句必须以分号(;)分隔,建议加上 ...

  • SQL必知必会(笔记)

    由于本人使用的mac,第一次涉及数据库方面知识,软件与环境配置都不是那么熟悉,安装MySQL还有GUI客户端的安装...

  • 《SQL必知必会 第4版》PDF高清完整版-免费下载

    《SQL必知必会 第4版》PDF高清完整版-免费下载 《SQL必知必会 第4版》PDF高清完整版-免费下载 下载地...

网友评论

      本文标题:《SQL必知必会》笔记7-高级联结(as、self-join、o

      本文链接:https://www.haomeiwen.com/subject/xormkxtx.html