Theta连接、等值连接和自然连接的区别

112

我在理解关系代数中的θ连接、等值连接和自然连接时遇到了困难。请问有人可以帮我更好地理解吗?如果我在θ连接中使用=符号,是否完全等同于使用自然连接?


关于赏金中的引语问题...他在那里并没有引用Codd,而是引用了我的答案,他的评论就在我的答案下面。 - heisenberg
Theta-join是“关系JOIN {属性运算符属性}关系”的表达式。人们常说“theta-join”,但实际上他们指的是theta-join的泛化形式,“关系JOIN {谓词}关系”。(类似于SQL INNER JOIN ON的模拟。) - philipxy
7个回答

171

Theta Join允许任意比较关系(例如≥)。

Equijoin是使用等式运算符的Theta Join。

Natural Join是在每个关系中具有相同名称的属性上进行的Equijoin。

此外,Natural Join会删除涉及等式比较的重复列,因此只剩下每个比较列中的1列;用粗略的关系代数术语表示为: ⋈ = πR,S-as ○ ⋈aR=aS


14
自然连接将删除具有相同名称的列。 - Bogdan Gavril MSFT
2
全部都要还是除了一个之外都要? - Christopher Shroba
2
@outis,“theta join”中的“theta”是什么意思? - Pacerier
3
历史上,theta连接中的“theta”是指作为连接标准的任意条件。(参见Garcia-Molina、Ullman、Widom所著《数据库系统:完整教程》第2章Theta Join) - Ram Rajamony
1
@SebastianPalma,我刚刚撤销了你用图片替换文本的做法。请[使用文本而不是图像/链接来表示文本--包括表格和ERDs。(https://meta.stackoverflow.com/q/285551/3404097) 只有那些无法使用文本表达或需要增强文本的内容才应该使用图像。 图像无法被搜索或剪切粘贴。 在图像中包含图例/键和解释。 - philipxy
显示剩余6条评论

65
虽然解释确切差异的答案很好,但我想展示关系代数如何转换为SQL以及3个概念的实际价值。
您问题中的关键概念是连接(join)。要理解连接,您需要了解笛卡尔积(该示例基于SQL,其中等效项称为交叉连接);
在实践中,这并不是非常有用。考虑以下示例。
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乘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是用来为这些产品添加更多价值的。我们真正想要的是将产品与它的相关组件“连接”起来,因为每个组件都属于一个产品。使用JOIN可以完成这个任务:

Product JOIN Component ON Pname

相关的SQL查询语句如下(你可以在这里尝试所有的例子)。
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行,因为笔记本电脑有3个组件,汽车有1个组件,而飞机没有组件。这更加有用。
回到你的问题,你提出的所有连接都是我刚才展示的JOIN的变体:
自然连接=连接(ON子句)基于具有相同名称的所有列;它从结果中删除重复的列,与所有其他连接不同;大多数DBMS(由各种供应商创建的数据库系统,如Microsoft的SQL Server、Oracle的MySQL等)甚至不费心支持它,这只是一种糟糕的实践(或者故意选择不实现)。想象一下,开发人员更改了产品中第二列的名称,将价格改为成本。然后,所有自然连接都将在PName和Cost上执行,导致0行,因为没有匹配的数字。
Theta连接=这是每个人都使用的通用连接,因为它允许您指定条件(在SQL中的ON子句)。您可以根据几乎任何条件连接,例如前两个字母相似或价格不同的产品。在实践中,这很少发生-在95%的情况下,您将在平等条件下连接,这使我们进入: Equi Join = 在实践中最常见的连接类型。上面的示例是等值连接。数据库针对这种连接进行了优化!等值连接的相反是非等值连接,即当您在除“=”以外的条件上进行连接时。数据库没有为此进行优化!它们都是一般Theta连接的子集。自然连接也是Theta连接,但条件(Theta)是隐含的。

信息来源:大学+认证的SQL Server开发人员+最近完成了斯坦福大学的MOO“数据库简介”,因此我敢说我对关系代数有新鲜的记忆。


1
你有些随意地使用了“笛卡尔积”这个术语。关系运算符的积会产生一个关系(与所有关系运算符一样!)。在SQL中,“CROSS JOIN”操作会产生一个表达式(行列)。集合运算符的笛卡尔积结果是一组对。 - onedaywhen
3
当你说“数据库”时,实际上是指“数据库管理系统(DBMSs)”,这在涉及“概念”时是一个至关重要的区别。 - onedaywhen
3
onedaywhen - 感谢您提供的所有有用评论!感觉就像是代码审查 :)。我已经修复了笛卡尔积和DBMS问题。我坚持认为自然连接只具有学术研究价值,而像SQL Server这样重要的DBMS有意不实现它 - 显式添加条件会导致更好的代码理解和维护。相关问题:https://dev59.com/om445IYBdhLWcg3wfKgZ - Bogdan Gavril MSFT
1
@HLGEM: 有人也可能对“SELECT * FROM…”提出类似的反对意见(也许您确实这样做)。但它是语言的一部分,存在于每个SQL实现中,而且我经常使用它(我打赌您也是!)提示并非所有代码都是生产代码。 - onedaywhen
2
“自然连接”列的真正问题不在于更改名称,而在于添加新列,这些列在系统中所有可能连接的表之间不得冲突。例如,“名称”、“描述”等非常常见的列。使用“自然连接”将使它们连接起来,而这是无意义的,违反了业务逻辑并导致错误。因此,“自然连接”是危险的。它强制您具有除(主/外)键列以外的不同名称,并且失去了“名称空间”。 - LoganMzz
显示剩余7条评论

15

@outis的答案很好:在关系方面简明且正确。

然而,在SQL方面,情况略微复杂。

考虑通常的供应商和零件数据库,但是在SQL中实现:

SELECT * FROM S NATURAL JOIN SP;

将返回一个结果集,其中包含以下列:

SNO,SNAME,STATUS,CITY,PNO,QTY

连接是在两个表中具有相同名称的列SNO上执行的。请注意,结果集有六列,仅包含一个SNO列。

现在考虑一个theta等值连接,其中连接的列名必须明确指定(还需要范围变量SSP):

SELECT * FROM S JOIN SP ON S.SNO = SP.SNO;
结果集将有七列,包括两列 SNO。结果集的名称被 SQL 标准称为“实现相关”,但可能如下所示: SNO, SNAME, STATUS, CITY, SNO, PNO, QTY 或者可能像这样: S.SNO, SNAME, STATUS, CITY, SP.SNO, PNO, QTY 换句话说,在 SQL 中,NATURAL JOIN 可以被认为是从结果集中删除具有重复名称的列(但遗憾的是不会删除重复行 - 你必须自己记得将 SELECT 更改为 SELECT DISTINCT)。
我不太清楚执行 SELECT * FROM table_expression; 的结果是什么。我知道它不是关系,因为它可以具有重复名称的列,或者没有名称的列,等等其他原因。我知道它不是一个集合,因为列的顺序很重要。它甚至不是 SQL 表或 SQL 表达式。我把它称为结果集。

同样适用于 JOIN ... USING(...) - Benoit
为什么你会说“我不太清楚SELECT * FROM table_expression;的结果是什么”? - Pacerier
@Pacerier:嗯,因为我不知道它是什么!上次我查看时,SQL标准避免定义它是什么。我知道它不是什么(不是关系、不是集合、不是表、不是表达式)。所以为了方便起见,我使用了自己的术语“结果集”。请注意,在关系模型中,涉及两个关系的操作的结果是一个关系。据我所知,对于SQL来说不能做出等价的陈述。 - onedaywhen

14

自然连接是等值连接的子集,等值连接又是Theta连接的子集。

如果我在Theta连接中使用=符号,这是否与仅使用自然连接完全相同?

不一定,但它将是等值连接。自然连接意味着您正在匹配所有同名列,而等值连接仅表示您专门使用“=”(而不是“小于”,“like”等)。

不过这纯属学术性质,你可以在关系型数据库工作多年,从未听到任何人使用这些术语。


3
在Codd最初的代数中,自然连接是连接的基本类型,而等值连接或θ连接被称为NJ(例如叉积)后跟限制的简写形式。 "自然连接是等值连接的子集,等值连接是θ连接的子集",这意味着每个NJ也可以表示为EJ或TJ。如果σ 1=1(A x B)算作等值连接,那么我认为这是正确的,因为在这种形式下,关系代数的每个操作都可以表示为等值连接。这里存在的歧义是RA存在多组基本运算符。 - nvogel
2
@EricFail:sqlvogel只是引用了kekekela的答案,而没有引用Codd的任何内容。如果你想了解更多关于Codd在连接(θ或其他)方面的著作,可以尝试阅读《数据库管理的关系模型》,或者逐步阅读他的参考文献 - outis
1
你链接的问题有一个答案,它接近于你所寻找的,可能是尽可能接近的。它链接到数据库子语言的关系完备性。第10页描述了θ、=和自然连接之间的联系(尽管在Codd的公式中,自然连接不严格属于=的子集,而是=连接的投影)。 - outis
@outis,谢谢。关于我正在寻找的内容,我正在寻找一个技术上解释“自然数是Equi的子集,而Equi又是Theta的子集”的参数。从技术上讲,你回答了我的问题。如果你将其作为答案添加进去,我会授予你奖励。 - Eric Fail
@outis,我有一个问题(http://stackoverflow.com/questions/15010966/can-the-natural-join-be-seen-as-a-subset-of-the-equi-join-and-theta-join),我正在尝试了解自然连接、等值连接和θ连接之间的关系,但是没有一个答案真正明确。我受到这个帖子的启发,因为我认为Codd曾经说过一些关于它们之间关系的话,如果这些连接可以有意义地被看作彼此的子集,并且这个位置在技术上可以被捍卫。我猜测Codd没有说过它们是彼此的子集。 - Eric Fail
显示剩余5条评论

12

Theta Join(θ连接):当您使用任何运算符进行连接查询(例如,=,<,>,>=等),那么该查询就属于θ连接。

Equi Join(等值连接):当您仅使用等式运算符进行连接查询时,则该查询属于等值连接。

示例:

> SELECT * FROM Emp JOIN Dept ON Emp.DeptID = Dept.DeptID;
> SELECT * FROM Emp INNER JOIN Dept USING(DeptID)
这将显示:
 _________________________________________________
| Emp.Name | Emp.DeptID | Dept.Name | Dept.DeptID |
|          |            |           |             |

注意:等值连接也是θ连接!

Natural Join(自然连接):一种隐式发生的等值连接,通过比较两个表中所有相同名称的列来实现。

注意:在这里,连接结果每对相同命名列只有一个列。

示例:

 SELECT * FROM Emp NATURAL JOIN Dept
这将显示:
 _______________________________
| DeptID | Emp.Name | Dept.Name |
|        |          |           |

0

两个表的笛卡尔积给出了所有可能的元组组合,就像数学中两个集合的叉积一样。由于很多时候内存中有一些垃圾值占用了不必要的空间,所以连接操作就派上用场了,它只给出那些需要且有意义的属性值的组合。

内连接会在表中重复显示字段,而自然连接通过过滤重复列并仅显示一次来解决这个问题。否则,两者的工作方式相同。自然连接更有效率,因为它保留了内存。此外,自然连接还消除了冗余。

两个表的等值连接是仅显示与另一个表中的值匹配的元组。例如:假设new1和new2是两个表。如果SQL查询select * from new1 join new2 on new1.id = new.id(id是两个表中相同的列),则从new2表开始,并加入与第二个表中的id匹配的内容。此外,非等值连接没有等号运算符,它们有<,>和between运算符。

θ连接包括所有比较运算符,包括等式和其他比较运算符<,>。当使用等式(=)运算符时,它被称为等值连接。


0

自然连接:当两个关系中至少有一个共同属性时,可以进行自然连接。

Theta 连接:当两个关系在特定条件下操作时,可以进行 Theta 连接。

等值连接:当两个关系在等值条件下操作时,可以进行等值连接。它是 Theta 连接的一种类型。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接