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

118

似乎要想将两个或多个表合并,我们可以使用join或where。那么其中一个方法相较于另一个方法有何优势呢?


2
根据您的使用情况,可能会产生相同的结果,但使用JOIN可以进行其他类型的关联。 - zneak
这个回答解决了你的问题吗?INNER JOIN ON vs WHERE clause - philipxy
6个回答

173

涉及多个表格的任何查询都需要某种形式的关联来将来自表格 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-92 JOIN 语法而不是 ANSI-89:

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

从设计的角度来看:


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

  • 查询的目的更明显;应用程序使用的列是清晰的
  • 它遵循了使用严格类型化的模块化规则。显式几乎普遍更好。

结论


除了熟悉和/或舒适度外,我没有看到继续使用 ANSI-89 WHERE 子句而不是 ANSI-92 JOIN 语法的任何好处。有些人可能会抱怨 ANSI-92 语法更冗长,但这正是使它显式的原因。越明确,理解和维护就越容易。


14
任何涉及多个表格的查询都需要某种形式的关联来将表格'A'和表格'B'的结果连接起来。否则,你将得到一个笛卡尔积(Cartesian Product),而你可能不希望出现这种情况(这些笛卡尔积会产生糟糕的结果)。 - Scott Smith

12

使用where语法(也称隐式连接)存在以下问题:

首先,由于连接条件不紧跟表名,很容易发生意外的交叉连接。如果有6个表被连接在一起,在where子句中可能会漏掉其中一个。你会看到很多人通过使用distinct关键字来修复这个问题,但这对数据库来说是巨大的性能损失。使用显式连接语法时,无法发生意外的交叉连接,因为它将失败于语法检查。

在某些数据库中,使用旧语法进行右连接和左连接会出现问题(在SQL Server中,你不能保证得到正确的结果)。此外,我知道SQL Server已经弃用了这种写法。

如果你打算使用交叉连接,在旧语法中就不清楚了。但是使用当前的ANSII标准可以清楚地表示。

使用隐式语法让维护人员更难以确定哪些字段是连接的一部分,甚至哪些表以什么顺序连接在一起,这意味着修改查询可能需要更多时间。我认识很少有人在熟悉显式连接语法后会回到旧方式。

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

老实说,你会使用18年前就已经被更好的方法所取代的任何其他代码吗?


9

大多数人倾向于使用JOIN语法,因为它更清晰地表明了正在连接的内容。此外,它还具有标准化的好处。

个人而言,我“成长”于WHERE语法,但是我越来越多地使用JOIN语法,越发认识到它更加清晰易懂。


1
@nawfal 我明白 - 我从旧式语法中成长,但一旦我习惯了新的语法,好处就变得清晰了,例如更难出现交叉连接错误,更加明确,更容易看出什么是连接和什么是过滤器等等...我变得着迷了。 - Basic

7

明确的连接传达了意图,将过滤留给where子句。这样更加清晰且符合标准,您可以执行左外连接或右外连接等操作,而仅使用where则更难实现。


4

您无法使用WHERE来组合两个表格。不过,您可以这样编写:

SELECT * FROM A, B
WHERE ...

这里的逗号相当于写成:
SELECT *
FROM A
CROSS JOIN B
WHERE ...

你会写这个吗?不会 - 因为这根本不是你想要的。你不需要交叉连接,你需要一个内部连接。但是当你写逗号时,你实际上在使用交叉连接,这很令人困惑。


0

实际上,你经常需要同时使用“WHERE”和“JOIN”。

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

例如,“LEFT JOIN”检索左表中的所有行以及右表中匹配的行。但是,这不会根据任何特定值或不属于JOIN的其他列筛选记录。因此,如果您想进一步过滤此结果,请在WHERE子句中指定额外的过滤器。


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