目录
本文介绍 SQL 如何使用内联结(INNER JOIN)、外联结(OUTER JOIN)和交叉联结(CROSS JOIN)。简单来说,就是将其他表中的列添加过来,进行“添加列”的运算。
本文重点
- 联结(JOIN)就是将其他表中的列添加过来,进行“添加列”的集合运算。UNION 是以行(纵向)为单位进行操作,而联结则是以列(横向)为单位进行的。
- 联结大体上分为内联结和外联结两种。首先请大家牢牢掌握这两种联结的使用方法。
- 请大家一定要使用标准 SQL 的语法格式来写联结运算,对于那些过时的或者特定 SQL 中的写法,了解一下即可,不建议使用。
一、什么是联结
在 SQL 如何进行并集、交集、差集等集合运算 中,我们学习了 UNION 和 INTERSECT 等集合运算,这些集合运算的特征就是以行方向为单位进行操作。
通俗地说,就是进行这些集合运算时,会导致记录行数的增减。使用 UNION 会增加记录行数,而使用 INTERSECT 或者 EXCEPT 会减少记录行数 [1]。
但是这些运算不会导致列数的改变。作为集合运算对象的表的前提就是列数要一致。因此,运算结果不会导致列的增减。
本文将要学习的联结(JOIN)运算,简单来说,就是将其他表中的列添加过来,进行“添加列”的运算(图 5)。该操作通常用于无法从一张表中获取期望数据(列)的情况。
截至目前,我们介绍的示例基本上都是从一张表中选取数据,但实际上,期望得到的数据往往会分散在不同的表之中。使用联结就可以从多张表(3 张以上的表也没关系)中选取数据了。
图 5 联结的图示
SQL 的联结根据其用途可以分为很多种类,这里希望大家掌握的有两种,内联结和外联结。接下来,我们就以这两种联结为中心进行学习。
二、内联结——INNER JOIN
首先我们来学习内联结(INNER JOIN),它是应用最广泛的联结运算。大家现在可以暂时忽略“内”这个字,之后会给大家详细说明。
本例中我们会继续使用 Product 表和 什么是 SQL 谓词 创建的 ShopProduct 表。下面我们再来回顾一下这两张表的内容。
表 1 Product(商品)表
product_id(商品编号)product_name(商品名称)product_type(商品种类)sale_price(销售单价)purchase_price(进货单价)regist_date(登记日期)0001T 恤衫衣服10005002009-09-200002打孔器办公用品5003202009-09-110003运动 T 恤衣服400028000004菜刀厨房用具300028002009-09-200005高压锅厨房用具680050002009-01-150006叉子厨房用具5002009-09-200007擦菜板厨房用具8807902008-04-280008圆珠笔办公用品1002009-11-11表 2 ShopProduct(商店商品)表
shop_id(商店编号)shop_name(商店名称)product_id(商品编号)quantity(数量)000A东京000130000A东京000250000A东京000315000B名古屋000230000B名古屋0003120000B名古屋000420000B名古屋000610000B名古屋000740000C大阪000320000C大阪000450000C大阪000690000C大阪000770000D福冈0001100对这两张表包含的列进行整理后的结果如表 3 所示。
表 3 两张表及其包含的列
ProductShopProduct商品编号○○商品名称○商品种类○销售单价○进货单价○登记日期○商店编号○商店名称○数量○如上表所示,两张表中的列可以分为如下两类。
A:两张表中都包含的列 → 商品编号
B:只存在于一张表内的列 → 商品编号之外的列
所谓联结运算,一言以蔽之,就是“以 A 中的列作为桥梁,将 B 中满足同样条件的列汇集到同一结果之中”,具体过程如下所述。
从 ShopProduct 表中的数据我们能够知道,东京店(000A)销售商品编号为 0001、0002 和 0003 的商品,但这些商品的商品名称(product_name)和销售单价(sale_price)在 ShopProduct 表中并不存在,这些信息都保存在 Product 表中。大阪店和名古屋店的情况也是如此。
下面我们就试着从 Product 表中取出商品名称(product_name)和销售单价(sale_price),并与 ShopProduct 表中的内容进行结合,所得到的结果如下所示:- shop_id | shop_name | product_id | product_name | sale_price
- ----------+-----------+-------------+--------------+-------------
- 000A | 东京 | 0002 | 打孔器 | 500
- 000A | 东京 | 0003 | 运动T恤 | 4000
- 000A | 东京 | 0001 | T恤衫 | 1000
- 000B | 名古屋 | 0007 | 擦菜板 | 880
- 000B | 名古屋 | 0002 | 打孔器 | 500
- 000B | 名古屋 | 0003 | 运动T恤 | 4000
- 000B | 名古屋 | 0004 | 菜刀 | 3000
- 000B | 名古屋 | 0006 | 叉子 | 500
- 000C | 大阪 | 0007 | 擦菜板 | 880
- 000C | 大阪 | 0006 | 叉子 | 500
- 000C | 大阪 | 0003 | 运动T恤 | 4000
- 000C | 大阪 | 0004 | 菜刀 | 3000
- 000D | 福冈 | 0001 | T恤衫 | 1000
复制代码 能够得到上述结果的 SELECT 语句如代码清单 9 所示。
代码清单 9 将两张表进行内联结
SQL Server DB2 PostgreSQL MySQL- SELECT SP.shop_id, SP.shop_name, SP.product_id, P.product_name, P.sale_price
- FROM ShopProduct AS SP INNER JOIN Product AS P -----①
- ON SP.product_id = P.product_id;
复制代码特定的 SQL
在 Oracle 的 FROM 子句中不能使用 AS(会发生错误)。因此,在 Oracle 中执行代码清单 9 时,请将 ① 的部分变为“FROM ShopProduct SP INNER JOIN Product P”。
关于内联结,请大家注意以下三点。
2.1 内联结要点 ① ——FROM 子句
第一点要注意的是,之前的 FROM 子句中只有一张表,而这次我们同时使用了 ShopProduct 和 Product 两张表。- FROM ShopProduct AS SP INNER JOIN Product AS P
复制代码 使用关键字 INNER JOIN 就可以将两张表联结在一起了。SP 和 P 分别是这两张表的别名,但别名并不是必需的。
在 SELECT 子句中直接使用 ShopProduct 和 product_id 这样的表的原名也没有关系,但由于表名太长会影响 SQL 语句的可读性,因此还是希望大家能够习惯使用别名 [2]。
法则 3
进行联结时需要在 FROM 子句中使用多张表。
2.2 内联结要点 ②—— ON 子句
第二点要注意的是 ON 后面的联结条件。- ON SP.product_id = P.product_id
复制代码 我们可以在 ON 之后指定两张表联结所使用的列(联结键),本例中使用的是商品编号(product_id)。
也就是说,ON 是专门用来指定联结条件的,它能起到与 WHERE 相同的作用。需要指定多个键时,同样可以使用 AND、OR。
在进行内联结时 ON 子句是必不可少的(如果没有 ON 会发生错误),并且 ON 必须书写在 FROM 和 WHERE 之间。
法则 4
进行内联结时必须使用 ON 子句,并且要书写在 FROM 和 WHERE 之间。
举个比较直观的例子,ON 就像是连接河流两岸城镇的桥梁一样(图 6)。
图 6 使用 ON 进行两表加法运算(和集)的图示
联结条件也可以使用“=”来记述。在语法上,还可以使用 |