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

好像要合并两个或多个表,我们可以使用join或where。 彼此有什么优势?

涉及多个表的任何查询都需要某种forms的关联,以将表“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 

从性能angular度来看:


如果支持(Oracle 9i +,PostgreSQL 7.2 +,MySQL 3.23 +,SQL Server 2000+),那么使用其他语法就没有任何性能优势。 优化器将它们视为相同的查询。 但是更复杂的查询可以从使用ANSI-92语法中受益:

  • 能够控制JOIN顺序 – 扫描表的顺序
  • 能够在join之前在表格上应用过滤条件

从维护的angular度来看:


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

  • 更可读,因为JOIN标准与WHERE子句是分开的
  • 不太可能错过JOIN标准
  • 对INNER以外的JOINtypes提供一致的语法支持,使得查询在其他数据库上易于使用
  • WHERE子句只用作所join表格的笛卡尔积的过滤

从deviseangular度看:


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

  • 查询的目的更为明显; 应用程序使用的列是清楚的
  • 它遵循关于尽可能使用严​​格types的模块化规则。 显式几乎普遍更好。

结论


由于缺乏熟悉性和/或舒适性,我没有看到继续使用ANSI-89 JOIN语法而不是ANSI-92语法的好处。 有些人可能会抱怨ANSI-92的语法比较冗长,但这就是明确的。 越明确,越容易理解和维护。

这些是使用where语法的问题(其他方式称为隐式连接):

首先,因为连接条件不在表名旁边,所以非常容易得到意外的交叉连接。 如果你有6个表连接在一起,很容易错过where子句中的一个。 通过使用distinct关键字,您会看到这个问题经常被修复。 这是数据库的巨大性能。 您不能使用显式连接语法来意外交叉连接,因为它将无法进行语法检查。

在某些数据库的旧语法中,左右连接是有问题的(在SQl服务器中,您不能保证获得正确的结果)。 更进一步,他们在我知道的SQL Server中不推荐使用。

如果您打算使用交叉连接,那么从旧的语法中就不清楚了。 使用当前的ANSII标准是明确的。

维护者很难确切地看到哪些字段是连接的一部分,甚至使用隐式语法以什么顺序将哪些表连接在一起。 这意味着可能需要更多时间来修改查询。 我知道很less有人一旦花时间对显式连接语法感到舒服,就回到了老路。

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

老实说,你会用18年前用更好的方法代替的其他types的代码吗?

大多数人倾向于发现join什么的JOIN语法有点清晰。 此外,它有一个标准的好处。

就个人而言,我在WHERE上“长大”,但我越用JOIN语法,我越看清楚它是如何更清晰的。

显式连接传达intent,留下where子句做过滤。 它是更清洁,它是标准的,你可以做的事情,如左外部或右外部这是很难做的,只有在哪里。

你不能使用WHERE来组合两个表。 你可以做什么虽然是写:

 SELECT * FROM A, B WHERE ... 

这里的逗号相当于写作:

 SELECT * FROM A CROSS JOIN B WHERE ... 

你会写吗? 不 – 因为这不是你的意思。 你不想交叉连接,你想要一个INNER JOIN。 但是,当你写逗号,你说的CROSS JOIN,这是混乱。

其实你经常需要“WHERE”和“JOIN”。

“JOIN”用于从两个表中检索数据 – 基于公共列的值。 如果您希望进一步筛选此结果,请使用WHERE子句。

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