1

我有一个关于 MySQl 中的内部联接的问题。根据我对 MySQL 的有限理解,内部联接生成的结果表仅包含两个表中都存在的行。也就是说,例如,如果 table1 包含 Joe 的行和 Sally 的行,而 table2 仅包含 Sally 的行,则内部连接将仅包含一行:Sally 的行。

例如:

在包含 2 个表的数据库中,

表一(宠物)

petName petType
Unicorn Horse
Pegasus Horse
Lion Cat

表2(颜色)

petName petColor
Unicorn white
Unicorn silver
Fish Gold

使用查询

SELECT * FROM Pet,Color WHERE Pet.petName = Color.petName

为什么是查询结果?

petName petType petName petColor
Unicorn Horse   Unicorn white
Unicorn Horse   Unicorn silver

为什么在表 1 中只有 1 只“独角兽马”时,第二行有“独角兽马”?我是否正确地说 MySQL 匹配表 1 和表 2 中的术语“独角兽”,并列出两个表中包含“独角兽”一词的行。然而,这样做会导致

petName petType petName petColor
Unicorn Horse   Unicorn white
<   NULL   >   Unicorn silver

MySQL 自动将值替换为表一中的“Unicorn Horse”行,因为它与查询中使用的“Unicorn”关键字匹配?

如果是这样,这有什么意义,因为 MySQL 只会在第二行给我多余的数据,而我没有用?另外,我可以通过使用来解决这个问题吗

SELECT * FROM Pet LEFT JOIN Color
ON Pet.petName=Color.petName
WHERE Pet.petName="Unicorn"?

我在 PHP & MYSQL for Dummies 中遇到了这个示例,但似乎无法理解。如果有好心人能澄清这一点,我将不胜感激。

4

6 回答 6

3

结果符合预期。您正在将两个表与两个表上的列连接起来PetNameUnicorn HorseFrom tablePet在结果集中显示了两次,因为它在 table 上的两条记录上匹配Color

要进一步了解有关联接的更多信息,请访问以下链接:

于 2013-05-20T13:37:35.830 回答
2

如果你执行SELECT * from Pet, Color(不带WHERE子句),你会得到以下结果:

petName petType petName petColor
Unicorn Horse   Unicorn white
Pegasus Horse   Unicorn white
Lion    Cat     Unicorn white
Unicorn Horse   Unicorn silver
Pegasus Horse   Unicorn silver
Lion    Cat     Unicorn silver
Unicorn Horse   Fish    Gold
Pegasus Horse   Fish    Gold
Lion    Cat     Fish    Gold

这称为CROSS JOIN; SQL 服务器将从表 1 中获取每一行并将其与表 2 中的每一行进行匹配。

添加WHERE Pet.petName = Color.petName时,SQL Server 将过滤掉该子句不正确的所有行。因此,由于唯一petName定义了petColoris Unicorn,你就剩下

petName petType petName petColor
Unicorn Horse   Unicorn white
Unicorn Horse   Unicorn silver

如果您的查询改为WHERE Pet.petName != Color.petName,您将获得补语,或者

petName petType petName petColor
Pegasus Horse   Unicorn white
Lion    Cat     Unicorn white
Pegasus Horse   Unicorn silver
Lion    Cat     Unicorn silver
Unicorn Horse   Fish    Gold
Pegasus Horse   Fish    Gold
Lion    Cat     Fish    Gold

如果您只想要 Pet 中定义颜色的一行,您可以使用

SELECT * FROM Pet 
  WHERE EXISTS (SELECT * FROM Color where Color.petName = Pet.petName)

这将返回

petName petType
Unicorn Horse  

这个查询本质上意味着“选择所有行,Pet其中至少有一个Color为该宠物定义的行,按名称”。

这称为半联接,因为 SQL 服务器可能在Color幕后进行联接,但Color结果集中没有返回任何数据。由于没有返回数据,因此您将只从一次中Color获取每一行,而不管为任何给定定义的行数如何。PetColorpetName

于 2013-05-20T13:55:57.593 回答
1

如果“一侧有多行,另一侧有单行”,则重复单行值。

所以这是正确的:

petName petType petName petColor
Unicorn Horse   Unicorn white
Unicorn Horse   Unicorn silver

SQL 不能使用 INNER JOIN 生成它。

petName petType petName petColor
Unicorn Horse   Unicorn white
<   NULL   >   Unicorn silver

就是这么简单。

于 2013-05-20T13:37:57.590 回答
0

并不是说 MySQL 在第二行填充空数据。

您的查询字面意思是“给我 PetName 是马的两个表中的所有内容。

就 MySQL 而言,它不知道您希望 pet 中的第一个独角兽行是白色的,然后有一个与任何东西都不匹配的额外独角兽是银色的。相反,它说“我有这只独角兽,它有 2 个属性,白色和银色。根据我的第一张表,我知道所有的独角兽都是马。所以我有一只白马独角兽和一只银马独角兽。”

至于目的,您可以删除冗余数据。例如,如果每个企业有 1 个地址但有多个销售人员,您不想在每个销售人员上存储相同的地址,因为当需要进行更改时,您必须更新大量记录。

相反,您可以说“Testco 在大街 123 号。Bob、John、Sally 和 Frank 都是 Testco 的销售人员。” 那么“Bob 的地址是什么”这个问题的答案就是“123 Main street” 但是你看一下 Testco 的记录而不是 Bob 的记录。

于 2013-05-20T13:41:18.423 回答
0

你有一只独角兽宠物,有两种颜色,所以有两排。如果您在 Pet 中添加另一行,宠物名称为 unicorn 和一种神话生物,您将得到四个。

如果您正在考虑隐藏重复数据,那是一个演示问题。每个人仍然是独角兽,你只是没有展示它,因为你已经拥有了。做到这一点的唯一方法是“知道”它与上述方法相同。

于 2013-05-20T13:51:25.670 回答
0

这正如预期的那样。

您的查询将连接每个表中的 petName 列并返回匹配的结果。在这里,它从带有颜色的颜色表中的名称的宠物表中找到匹配Unicorn Horse项,然后从带有颜色的颜色表中的white名称的宠物表中找到第二个匹配项Unicorn Horsesilver

于 2013-05-20T13:38:35.660 回答