θ联接,等联接和自然联接之间的区别


92

当谈到theta联接,等联接和自然联接时,我很难理解关系代数。有人可以帮我更好地理解它吗?如果我在theta联接上使用=符号,是否与仅使用自然联接完全相同?


再次从悬赏中引用有问题的报价...他没有在这里引用Codd,而是在我的回答中引用了他的评论。
heisenberg 2013年

Answers:


138

theta连接允许任意的比较关系(如≥)。

一个等值连接是使用等于运算符theta连接。

一个自然连接是对那些在每个关系相同的名称属性的等值连接。

此外,自然联接会删除相等比较中涉及的重复列,因此每个比较列中仅保留1个;用关系代数的粗略术语: ⋈ = πR,S-as ○ ⋈aR=aS


13
自然联接将删除具有相同名称的列
Bogdan Gavril MSFT 2013年

2
所有这些,还是只有一个?
Christopher Shroba 2014年

如果两个表中的名称相同,Equijoin也会删除相等列。
Vishal R 2014年

1
@outis,“ theta join”中的“ theta”是什么意思?
Pacerier,2015年

2
@Pacerier:从历史上看,thetain theta 联接是指用作联接条件的任意条件。(请参阅数据库系统:由Garcia-Molina
撰写

55

虽然解释确切差异的答案很好,但我想展示如何将关系代数转换为SQL以及这三个概念的实际价值是什么。

您问题中的关键概念是联接的想法。要了解联接,您需要了解笛卡尔乘积(该示例基于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小提琴。您可以看到有12行= 3 x4。显然,像“笔记本电脑”和“ wheels”这样的行没有意义,这就是为什么在实践中很少使用笛卡尔积的原因。

|    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上

关联的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%的情况下,您将以平等条件加入,这导致我们:

等值连接 =实践中最常用的一种。上面的示例是一个等值连接。数据库针对此类连接进行了优化!等式联接的对面是非等号联接,即,当您在除“ =”以外的条件下联接时。数据库尚未为此优化!它们都是通用theta联接的子集。自然联接也是theta联接,但条件(theta)是隐式的。

信息源:大学+认证的SQL Server开发人员+最近完成了斯坦福大学的MOO“数据库简介”,所以我敢说我刚想到了关系代数。


1
您对“笛卡尔积”的使用有些宽松。关系运算符产品产生一个关系(与所有关系运算符相同!)CROSS JOINSQL中的一个运算产生一个表表达式(列的行)。设置操作的笛卡尔积产生一对对。
2013年

1
当您说“数据库”时,您实际上是指“ DBMS”,这是解决“概念”时的关键区别。
某天,2013年

2
onedaywhen-感谢您提供所有有用的评论!感觉像是一个代码审查:)。我修复了笛卡尔积和DBMS问题。我认为自然连接仅是学术上的关注,而重要的DBMS(例如SQL Server)并不是故意实现的-添加条件明确地导致了更好的代码理解和维护。一个相关的问题:stackoverflow.com/questions/4826613/natural-join-in-sql-server
Bogdan Gavril MSFT 2013年

1
@HLGEM:有人可能会反对SELECT * FROM...(也许你会这样做)。但这是用语言编写的,它是每个SQL实现中的语言,我经常使用它(我也打赌你也这样做!)提示并非所有代码都是生产代码。
某天,2013年

1
“自然”联接列的真正问题不在于更改名称,而是要添加新的名称,该名称不得在系统中所有可能的联接表之间发生冲突。采取非常常见的列,例如“名称”,“描述”,...使用“自然连接”将使它们连接,而这却是胡说八道,更多违反业务逻辑并导致错误。因此,是的,“自然加入”是危险的。它会迫使您使用唯一的名称(除了(主要/外部)键合),并失去“名称间隔”。
LoganMzz

14

@outis的回答很好:关于关系的简明扼要。

但是,就SQL而言,情况稍微复杂一些。

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

SELECT * FROM S NATURAL JOIN SP;

将返回带有列的结果集**

SNO, SNAME, STATUS, CITY, PNO, QTY

在两个表中具有相同名称的列上执行联接SNO。请注意,结果集有六列,而对于SNO

现在考虑一个theta eqijoin,其中必须明确指定联接的列名(加上范围变量,S并且SP是必需的):

SELECT * FROM S JOIN SP ON S.SNO = SP.SNO;

结果集将有7列,其中包括2列SNO。结果集的名称是SQL标准所称的“依赖于实现”,但看起来可能像这样:

SNO, SNAME, STATUS, CITY, SNO, PNO, QTY

也许这

S.SNO, SNAME, STATUS, CITY, SP.SNO, PNO, QTY

换句话说,NATURAL JOIN可以考虑在SQL中从结果集中删除具有重复名称的列(但是las不会删除重复的行-您必须记住要更改SELECTSELECT DISTINCT自己)。


**我不太清楚结果SELECT * FROM table_expression;是什么。我知道这不是关系,因为除其他原因外,它可能具有名称重复的列或没有名称的列。我知道这不是一个集合,因为除其他原因外,列顺序很重要。它甚至不是SQL表或SQL表表达式。我称它为结果集。


同样适用JOIN ... USING(...)
贝诺瓦特

为什么说“我不太清楚结果SELECT * FROM table_expression;是什么”
Pacerier

@Pacerier:嗯,因为我不知道这是什么!我上次查看时,SQL标准避免定义它的含义。我确实知道它不是什么(不是关系,不是集合,不是表,不是表表达式)。因此,为了便于参考,我使用了自己的术语“结果集”。注意,在关系模型中,涉及两个关系的运算结果是一个关系。无法对SQL AFAIK做出等效语句。
一天

11

自然是Equi的子集,而Equi是Theta的子集。

如果我在theta联接上使用=符号,是否与使用自然联接完全相同???

不一定,但这将是平等。自然表示您在所有名称相似的列上进行匹配,Equi表示您仅在使用“ =”(而不是“小于”,类似等)

虽然这是纯粹的学术界,但是您可以使用关系数据库多年,而且从未听说过有人使用这些术语。


我怀疑当您说“关系数据库”时,我怀疑您指的是其他东西,例如“ SQL”。
2011年

使用非SQL的关系数据库进行非学术研究吗?那么,您指的是什么产品?
2011年

3
在Codd的原始代数中,自然连接是连接的基本类型,而等号或theta-“连接”是NJ(例如叉积)的缩写,其后是一个限制。“自然是Equi的子集,它是Theta的子集”,这大概意味着每个NJ也可以表示为EJ或TJ。我想如果σ1 = 1(A x B)计算为等值连接,这是正确的,在这种情况下,关系代数的每个运算都可以表示为该形式的等值连接。此处的含糊之处在于,RA有不止一种可能的基本算子集。
nvogel 2012年

2
@EricFail:sqlvogel只是引用kekekela的答案,而不是来自Codd的任何内容。如果您想更多地了解Codd的有关联接(θ或其他)的著作,可以尝试“数据库管理的关系模型”,或者通过他的参考书目进行研究
outis

1
...您链接到的问题的答案与您要寻找的答案很接近,可能尽可能接近。它链接到数据库子语言的关系完整性。P. 10描述了θ,=和自然联接之间的联系(尽管自然不是严格意义上Codd公式中=的子集,而是=-联接的投影)。
outis

7

Theta联接: 当您使用任何运算符(例如=,<,>,> =等)进行联接查询时,该联接查询就会出现在Theta联接之下。

等值联接: 仅使用等号运算符查询联接时,该联接查询位于等联接下。

例:

>选择*从Emp JOIN部门打开Emp.DeptID = Dept.DeptID;
>选择*从Emp内部联接部门使用(DeptID)
这将显示:
 _________________________________________________
| Emp.Name | Emp.DeptID | 部门名称| Dept.DeptID |
| | | | |

注意:等值联接也是theta联接!

自然连接:自然连接 的一种,通过比较两个表中所有相同名称的列隐式出现。

注意:此处,对于每对相同名称的列,连接结果只有一个列。

 选择*来自Emp Natural Join部门
这将显示:
 _______________________________
| DeptID | Emp.Name | 部门名称|
| | | |

1

两表的笛卡尔积给出了元组的所有可能组合,如数学中的例子两组的叉积。因为很多时候,有些垃圾值也占用了内存中不必要的空间,所以这里的联接变得抢救起来,它们仅给出了那些必需且有意义的属性值的组合。

内部联接给表中的重复字段两次,而此处的自然联接通过仅过滤重复的列并仅显示一次来解决该问题。否则,两者的工作原理相同。自然连接会保留内存,因此效率更高。此外,自然连接中的冗余也被删除。

两个表的等值连接使得它们仅显示与其他表中的值匹配的那些元组。例如:让new1和new2是两个表。如果sql查询选择* from new1,则在new1.id = new.id上加入new2(id是两个表中的同一列),然后从new2表开始并进行与第二个表中的id匹配的联接。此外,非等号联接不具有等号运算符,它们具有<,>和在运算符之间。

theta join由所有比较运算符(包括相等)和其他<,>比较运算符组成。当它使用equals(=)运算符时,称为Equi join。


0

自然连接:当两个关系中至少有一个公共属性时,自然连接是可能的。

Theta连接:当两个在特定条件下运行时,Theta连接是可能的。

等值联接:当两个在等值条件下起作用时,等值点是可能的。这是theta联接的一种类型。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.