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

似乎可以组合两个或多个表,我们可以使用 join 或 where。一个比另一个有什么好处?

54035 次浏览

显式联接传递意图,留下 where 子句进行筛选。它是干净的,它是标准的,你可以做的事情,如左外或右外,这是很难做的,只有在哪里。

大多数人倾向于发现 JOIN 语法对于什么被连接到什么更清楚一些。此外,它还有成为标准的好处。

就我个人而言,我是在 WHERE 上“长大”的,但是我越多地使用 JOIN 语法,我就越开始看到它是如何变得更加清晰的。

您不能使用 WHERE 来组合两个表:

SELECT * FROM A, B
WHERE ...

这里的逗号相当于写:

SELECT *
FROM A
CROSS JOIN B
WHERE ...

你会写吗?不,因为你根本不是这个意思。你不想要一个交叉连接,你想要一个内部连接。但是当你写逗号的时候,你说的是 CROSS JOIN,这让人很困惑。

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

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

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

Here's the query re-written using ANSI-92 JOIN syntax:

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 子句
  • 不太可能错过加入标准
  • 对 INNER 以外的 JOIN 类型提供一致的语法支持,使查询更容易在其他数据库上使用
  • WHERE clause only serves as filtration of the cartesian product of the tables joined

从设计的角度来看:


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

  • The purpose of the query is more obvious; the columns used by the application is clear
  • 它遵循尽可能使用严格类型的模块化规则。

结论


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

These are the problems with using the where syntax (other wise known as the implicit join):

首先,很容易出现意外的交叉连接,因为连接条件不在表名的旁边。如果将6个表连接在一起,则很容易在 where 子句中漏掉一个表。通过使用 different 关键字,您会经常看到这个问题得到修复。这对数据库来说是一个巨大的性能打击。您不能使用显式的连接语法获得偶然的交叉连接,因为它将无法进行语法检查。

按照某些数据库的旧语法,右连接和左连接是有问题的(在 SQL 服务器中,不能保证获得正确的结果)。而且我知道在 SQLServer 中它们是不被推荐的。

如果您打算使用交叉联接,那么从旧语法中是不清楚的。使用当前的 ANSII 标准显而易见。

对于维护人员来说,使用隐式语法确切地查看哪些字段是联接的一部分,甚至哪些表以何种顺序联接在一起要困难得多。这意味着修改查询可能需要更多的时间。我认识的人中,很少有人会回到过去的老路上,一旦他们花时间对显式的 join 语法感到满意。

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

老实说,你会使用任何其他类型的代码,被替换为一个更好的方法18年前?

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

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

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