示例(不使用您的示例表 :-)
我有一家汽车租赁公司。
Table car
id: integer primary key autoincrement
licence_plate: varchar
purchase_date: date
Table customer
id: integer primary key autoincrement
name: varchar
Table rental
id: integer primary key autoincrement
car_id: integer
bike_id: integer
customer_id: integer
rental_date: date
简单吧?我有 10 条汽车记录,因为我有 10 辆汽车。
我经营这家公司 10 年了,所以我有 1000 名客户。
我每年每辆车的租金约为 20 倍 = 10 年 x 10 辆汽车 x 20 = 2000 次租金。
如果我将所有内容存储在一张大表中,我就有 10x1000x2000 = 2000 万条记录。
如果我将它存储在 3 个表中,我有 10+1000+2000 = 3010 条记录。
那是 3 个数量级,所以这就是我使用 3 个表的原因。
但因为我使用 3 个表 (以节省空间和时间) 我必须使用连接才能再次获取数据
(至少如果我想要名称和车牌而不是数字).
使用内部联接
客户 345 的所有租金?
SELECT * FROM customer
INNER JOIN rental on (rental.customer_id = customer.id)
INNER JOIN car on (car.id = rental.car_id)
WHERE customer.id = 345.
这是一个INNER JOIN,因为我们只想了解汽车linked to 租赁linked to 实际发生的客户。
请注意,我们还有一个bike_id,链接到bike table,它与car table 非常相似,但又有所不同。
我们如何为客户 345 获得所有自行车 + 汽车租赁服务。
我们可以尝试并做到这一点
SELECT * FROM customer
INNER JOIN rental on (rental.customer_id = customer.id)
INNER JOIN car on (car.id = rental.car_id)
INNER JOIN bike on (bike.id = rental.bike_id)
WHERE customer.id = 345.
但这会给出一个空集!!
这是因为租赁可以是bike_rental 或car_rental,但不能同时是两者。
不工作的inner join 查询只会为我们在同一交易中同时租用自行车和汽车的所有租赁提供结果。
我们正在尝试使用布尔值AND 加入。
使用外连接
为了解决这个问题,我们需要一个outer join。
让我们用left join解决它
SELECT * FROM customer
INNER JOIN rental on (rental.customer_id = customer.id) <<-- link always
LEFT JOIN car on (car.id = rental.car_id) <<-- link half of the time
LEFT JOIN bike on (bike.id = rental.bike_id) <<-- link (other) 0.5 of the time.
WHERE customer.id = 345.
这样看。 inner join 是 AND,left join 是 OR,如以下伪代码所示:
if a=1 AND a=2 then {this is always false, no result}
if a=1 OR a=2 then {this might be true or not}
如果您创建表并运行查询,您可以看到结果。
关于术语
left join 与 left outer join 相同。
没有额外前缀的 join 是 inner join
还有一个full outer join。在 25 年的编程生涯中,我从未使用过它。
为什么要离开
这里有两张桌子。在我们链接的示例中
客户使用inner join 租用,在内部连接两个表必须链接,所以left:customer 表和right:rental 表之间没有区别。
下一个链接是位于left:rental 和right:car 之间的left join。在左侧,所有行都必须链接,而右侧则不必。这就是为什么它是left join