注意
首先我们要知道,联结并不是一种数据库自带的操作,只是我们自己进行的操作,我们给这种操作起了一个名字:联结。
其实就是我们常说的构建临时表。
笛卡尔积
了解联结之前,我们要了解什么是笛卡尔积。
这是一张customer表:
这是一张订单(order)表:
这是两张表数据的笛卡尔积:
可见笛卡尔积就是将两张表的数据交叉相乘,这种情况往往是没有联结条件的表关系在联结操作的时候返回的值,正如上图所示,SELECT是没有WHERE的。
联结
联结只是一种操作的名字,不是数据库自带的。就像我们给倒水这个行为取了一个叫“倒水”的名字一样。联结都是可以和子查询进行互换的。
等值联结
又叫内部联结,基于两表之间的相等测试。
这就是一个等值联结(AS设置表的别名):
当然我们也可以这样写,这样更像是内部联结,但结果都是一样的:
进而,我们可以在这样的基础上查询订单价格在100以上的用户姓名。
自联结
就是自己和自己的联结,可以与子查询相互转换。
比如,现在我们有这个问题:我们知道ID为TNT的商品有问题,现在我们想知道生产这一商品的供应商生唱的其他商品都是哪些?并且这些数据都存在一张表中。
我们可以使用子查询:
SELECT product_id,product_name
FROM products
WHERE supplier_id=(SELECT spplier_id
FROM products
WHERE product_id='TNT');
我们也可以使用自联结:
SELECT product_id,product_name
FROM products AS p1,products AS p2
WHERE p1.sppulier_id=p2.spplier_id
AND p1.spplier_id='TNT';
自然联结
内部联结往往会出现重复的列。如图,有两个cust_id:
自然联结就是为了避免重复列出现,其实也就是一种自主选择搜索列的“行为”,我们给取了一个不同于内部联结的名字。
如图,就是一个自然联结。使用了c.*和o.order_price来做代替:
外部联结
许多时候我们会遇到这种需求:对每个用户下了多少单进行统计,包括那些没有下单的用户。
问题是,没有下单的用户就不会出现在订单表里,即会出现customers表中的某一行(即某一个用户)没有和order表进行关联的情况。外部联结就是为了应对这种情况。
新增的customers表:
不变的orders表:
统计每个用户有哪些订单:
外部联结用关键字OUTER JOIN实现。注意,在使用OUTER JOIN时必须使用LEFT或者RIGHT来指定包括其所有行的表,LEFT OUTER JOIN就是对左边表的行进行全选,RIGHT OUTER JOIN就是对右边表的行进行全选。
最后
联结可以和子查询或者多次的查询进行互换,联结必须要有条件,即使是设置了外键也不能替代条件。