虽然解释确切差异的答案很好,但我想展示如何将关系代数转换为 SQL,以及这 3 个概念的实际价值是什么。
您问题中的关键概念是联接的概念。要了解联接,您需要了解笛卡尔积(该示例基于 SQL,其中等价的称为交叉联接,正如 onedaywhen 指出的那样);
这在实践中不是很有用。考虑这个例子。
Product(PName, Price)
====================
Laptop, 1500
Car, 20000
Airplane, 3000000
Component(PName, CName, Cost)
=============================
Laptop, CPU, 500
Laptop, hdd, 300
Laptop, case, 700
Car, wheels, 1000
笛卡尔积 Product x Component 将是 - 波纹管或sql fiddle。可以看到有 12 行 = 3 x 4。显然,像“笔记本电脑”和“轮子”这样的行没有意义,这就是为什么在实践中很少使用笛卡尔积的原因。
| PNAME | PRICE | CNAME | COST |
--------------------------------------
| Laptop | 1500 | CPU | 500 |
| Laptop | 1500 | hdd | 300 |
| Laptop | 1500 | case | 700 |
| Laptop | 1500 | wheels | 1000 |
| Car | 20000 | CPU | 500 |
| Car | 20000 | hdd | 300 |
| Car | 20000 | case | 700 |
| Car | 20000 | wheels | 1000 |
| Airplane | 3000000 | CPU | 500 |
| Airplane | 3000000 | hdd | 300 |
| Airplane | 3000000 | case | 700 |
| Airplane | 3000000 | wheels | 1000 |
JOIN 旨在为这些产品增加更多价值。我们真正想要的是将产品与其关联的组件“连接”起来,因为每个组件都属于一个产品。这样做的方法是使用连接:
Pname 上的产品 JOIN 组件
相关的 SQL 查询是这样的(你可以玩所有的例子here)
SELECT *
FROM Product
JOIN Component
ON Product.Pname = Component.Pname
结果:
| PNAME | PRICE | CNAME | COST |
----------------------------------
| Laptop | 1500 | CPU | 500 |
| Laptop | 1500 | hdd | 300 |
| Laptop | 1500 | case | 700 |
| Car | 20000 | wheels | 1000 |
请注意,结果只有 4 行,因为 Laptop 有 3 个组件,Car 有 1 个,Airplane 没有。这更有用。
回到您的问题,您询问的所有联接都是我刚刚展示的 JOIN 的变体:
自然连接 = 对所有同名列进行连接(ON 子句);它从结果中删除重复的列,而不是所有其他连接;大多数 DBMS(由各种供应商创建的数据库系统,如 Microsoft 的 SQL Server、Oracle 的 MySQL 等)甚至都不支持这一点,这只是一种不好的做法(或故意选择不实现它)。想象一下,一个开发人员来了,将 Product 中第二列的名称从 Price 更改为 Cost。然后所有自然连接都将在 PName 和 Cost 上完成,因为没有数字匹配,所以结果为 0 行。
Theta Join = 这是每个人都使用的一般连接,因为它允许您指定条件(SQL 中的 ON 子句)。您几乎可以在任何您喜欢的条件下加入,例如前 2 个字母相似或价格不同的产品。在实践中,这种情况很少发生 - 在 95% 的情况下,您将加入相等条件,这导致我们:
Equi Join = 实践中最常用的一种。上面的例子是一个 equi 连接。数据库针对这种类型的连接进行了优化!等值连接的对立面是非等值连接,即当您在“=”以外的条件下连接时。数据库没有为此优化!它们都是一般 theta 连接的子集。自然连接也是 theta 连接,但条件 (theta) 是隐式的。
信息来源:大学 + 认证的 SQL Server 开发人员 + 最近完成了斯坦福大学的 MOO“数据库简介”,所以我敢说我对关系代数有了新的认识。