似乎要想将两个或多个表合并,我们可以使用join或where。那么其中一个方法相较于另一个方法有何优势呢?
涉及多个表格的任何查询都需要某种形式的关联来将来自表格 A 的结果链接到表格 B。传统的(ANSI-89)做法是:
在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 语法中受益:
有许多原因要使用 ANSI-92 JOIN 语法而不是 ANSI-89:
ANSI-92 JOIN 语法是一种模式,而不是反模式:
除了熟悉和/或舒适度外,我没有看到继续使用 ANSI-89 WHERE 子句而不是 ANSI-92 JOIN 语法的任何好处。有些人可能会抱怨 ANSI-92 语法更冗长,但这正是使它显式的原因。越明确,理解和维护就越容易。
使用where语法(也称隐式连接)存在以下问题:
首先,由于连接条件不紧跟表名,很容易发生意外的交叉连接。如果有6个表被连接在一起,在where子句中可能会漏掉其中一个。你会看到很多人通过使用distinct关键字来修复这个问题,但这对数据库来说是巨大的性能损失。使用显式连接语法时,无法发生意外的交叉连接,因为它将失败于语法检查。
在某些数据库中,使用旧语法进行右连接和左连接会出现问题(在SQL Server中,你不能保证得到正确的结果)。此外,我知道SQL Server已经弃用了这种写法。
如果你打算使用交叉连接,在旧语法中就不清楚了。但是使用当前的ANSII标准可以清楚地表示。
使用隐式语法让维护人员更难以确定哪些字段是连接的一部分,甚至哪些表以什么顺序连接在一起,这意味着修改查询可能需要更多时间。我认识很少有人在熟悉显式连接语法后会回到旧方式。
我还注意到,一些使用隐式连接的人实际上并不理解连接的工作原理,因此在查询中得到了不正确的结果。
老实说,你会使用18年前就已经被更好的方法所取代的任何其他代码吗?
大多数人倾向于使用JOIN语法,因为它更清晰地表明了正在连接的内容。此外,它还具有标准化的好处。
个人而言,我“成长”于WHERE语法,但是我越来越多地使用JOIN语法,越发认识到它更加清晰易懂。
明确的连接传达了意图,将过滤留给where子句。这样更加清晰且符合标准,您可以执行左外连接或右外连接等操作,而仅使用where则更难实现。
您无法使用WHERE来组合两个表格。不过,您可以这样编写:
SELECT * FROM A, B
WHERE ...
SELECT *
FROM A
CROSS JOIN B
WHERE ...
你会写这个吗?不会 - 因为这根本不是你想要的。你不需要交叉连接,你需要一个内部连接。但是当你写逗号时,你实际上在使用交叉连接,这很令人困惑。
实际上,你经常需要同时使用“WHERE”和“JOIN”。
“JOIN”用于从两个表中检索数据 - 基于共同列的值。如果您想进一步过滤此结果,请使用WHERE子句。
例如,“LEFT JOIN”检索左表中的所有行以及右表中匹配的行。但是,这不会根据任何特定值或不属于JOIN的其他列筛选记录。因此,如果您想进一步过滤此结果,请在WHERE子句中指定额外的过滤器。