在MySQL查询中,为什么要使用join而不是在哪里?


108

似乎要合并两个或多个表,我们可以使用join或where。一个相对于另一个的优点是什么?


2
根据您的用法,它可能具有相同的结果,但是使用JOIN可以进行其他类型的关联。
zneak

这回答了你的问题了吗?INNER JOIN ON vs WHERE子句
philipxy

Answers:


160

任何涉及多个表的查询都需要某种形式的关联,以将结果从表“ A”链接到表“ B”。传统的(ANSI-89)方法是:

  1. 在FROM子句中列出逗号分隔列表中涉及的表
  2. 在WHERE子句中编写表之间的关联

    SELECT *
      FROM TABLE_A a,
           TABLE_B b
     WHERE a.id = b.id

这是使用ANSI-92 JOIN语法重写的查询:

SELECT *
  FROM TABLE_A a
  JOIN TABLE_B b ON b.id = a.id

从性能角度来看:


在受支持的地方(Oracle 9i +,PostgreSQL 7.2 +,MySQL 3.23 +,SQL Server 2000+),使用任何一种语法都不会对其他语法产生性能上的好处。优化器将它们视为相同的查询。但是更复杂的查询可以从使用ANSI-92语法中受益:

  • 控制JOIN顺序的能力-扫描表的顺序
  • 可以在加入表格之前在表格上应用过滤条件

从维护角度:


在ANSI-89上使用ANSI-92 JOIN语法的原因有很多:

  • 更具可读性,因为JOIN标准与WHERE子句分开
  • 不太可能错过JOIN标准
  • 对除INNER之外的JOIN类型的一致语法支持,使查询易于在其他数据库上使用
  • WHERE子句仅用作连接表的笛卡尔积的过滤

从设计角度来看:


ANSI-92 JOIN语法是模式,而不是反模式:

  • 查询的目的更加明显;应用程序使用的列很清楚
  • 它遵循关于尽可能使用严​​格类型的模块化规则。显式通用性更好。

结论


缺乏熟悉性和/或舒适性,我认为继续使用ANSI-89 WHERE子句代替ANSI-92 JOIN语法没有任何好处。有人可能会抱怨ANSI-92语法更冗长,但这正是它的明确之处。越明确,就越容易理解和维护。


14
“ ...任何涉及多个表的查询都需要某种形式的关联,以将表'A'的结果链接到表'B'...否则,您将得到笛卡尔积,而您可能不希望那样做。 (那些笛卡尔让糟糕的产品)。
斯科特·史密斯

8

大多数人倾向于将JOIN语法更清楚地了解要连接的内容。另外,它具有成为标准的好处。

就个人而言,我在“ WHERE”上“成长”,但是使用JOIN语法的次数越多,我就越会开始看到它的清晰性。


1
@nawfal我了解-我从小就习惯了旧式语法,但是一旦习惯了新语法,好处就显而易见了,例如,更难于错误地进行交叉联接,更明确,更容易了解什么是联接以及什么是联接。过滤器等...我迷上了。
2012年

8

这些是使用where语法(否则称为隐式联接)的问题:

首先,由于表名称旁边的联接条件并不正确,因此很容易发生意外的交叉联接。如果将6个表连接在一起,则很容易在where子句中遗漏一个表。通过使用distinct关键字,您会经常看到此修复程序。这对于数据库而言是巨大的性能损失。使用显式联接语法不会导致意外的交叉联接,因为它将无法通过语法检查。

右联接和左联接在某些数据库中的旧语法中存在问题(在SQl服务器中,不能保证您会获得正确的结果)。此外,我知道它们在SQL Server中已弃用。

如果您打算使用交叉联接,那么从旧语法来看并不清楚。使用当前的ANSII标准很明显。

对于维护人员而言,使用隐式语法很难确切地看到哪些字段是连接的一部分,甚至是哪些表以什么顺序连接在一起。这意味着修改查询可能需要更多时间。我认识的人很少,一旦他们花时间对显式联接语法感到满意,便回到了旧方法。

我还注意到,一些使用这些隐式联接的人实际上并不了解联接的工作原理,因此在查询中得到错误的结果。

老实说,您会使用18年前被更好的方法取代的任何其他类型的代码吗?



3

您不能使用WHERE合并两个表。但是,您可以做的是编写:

SELECT * FROM A, B
WHERE ...

这里的逗号相当于写:

SELECT *
FROM A
CROSS JOIN B
WHERE ...

你会写吗?不-因为这根本不是您的意思。您不需要交叉连接,而需要内部连接。但是,当您写逗号时,您是在说CROSS JOIN,这令人困惑。


0

实际上,您通常同时需要“ WHERE”和“ JOIN”。

“ JOIN”用于从两个表中检索数据-基于公共列的值。如果然后要进一步过滤此结果,请使用WHERE子句。

例如,“ LEFT JOIN”从左表检索所有行,再从右表检索匹配的行。但这不会过滤任何特定值或不属于JOIN的其他列上的记录。因此,如果要进一步过滤此结果,请在WHERE子句中指定其他过滤器。

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.