为简单起见,假设所有相关字段都为NOT NULL。

你可以:

SELECT
    table1.this, table2.that, table2.somethingelse
FROM
    table1, table2
WHERE
    table1.foreignkey = table2.primarykey
    AND (some other conditions)

否则:

SELECT
    table1.this, table2.that, table2.somethingelse
FROM
    table1 INNER JOIN table2
    ON table1.foreignkey = table2.primarykey
WHERE
    (some other conditions)

这两者在MySQL中工作方式相同吗?


当前回答

在ON / WHERE中应用条件语句

在这里,我解释了逻辑查询处理步骤。


参考:Microsoft®SQL Server™2005 T-SQL查询 出版社:微软出版社 时间:2006年3月7日 打印ISBN-10: 0-7356-2313-9 打印ISBN-13: 978-0-7356-2313-2 页:640

Microsoft®SQL Server™2005 T-SQL查询内部

(8)  SELECT (9) DISTINCT (11) TOP <top_specification> <select_list>
(1)  FROM <left_table>
(3)       <join_type> JOIN <right_table>
(2)       ON <join_condition>
(4)  WHERE <where_condition>
(5)  GROUP BY <group_by_list>
(6)  WITH {CUBE | ROLLUP}
(7)  HAVING <having_condition>
(10) ORDER BY <order_by_list>

SQL与其他编程语言不同的第一个值得注意的方面是代码处理的顺序。在大多数编程语言中,代码是按照编写的顺序处理的。在SQL中,处理的第一个子句是FROM子句,而首先出现的SELECT子句几乎是最后处理的。

每一步生成一个虚拟表,用作下一步的输入。这些虚拟表对调用方(客户端应用程序或外部查询)不可用。只有最后一步生成的表返回给调用者。如果在查询中没有指定某个子句,则简单地跳过相应的步骤。

逻辑查询处理阶段简要描述

如果对步骤的描述现在看起来没有多大意义,也不要太担心。这些都是作为参考提供的。场景示例之后的部分将更详细地介绍这些步骤。

FROM: A Cartesian product (cross join) is performed between the first two tables in the FROM clause, and as a result, virtual table VT1 is generated. ON: The ON filter is applied to VT1. Only rows for which the <join_condition> is TRUE are inserted to VT2. OUTER (join): If an OUTER JOIN is specified (as opposed to a CROSS JOIN or an INNER JOIN), rows from the preserved table or tables for which a match was not found are added to the rows from VT2 as outer rows, generating VT3. If more than two tables appear in the FROM clause, steps 1 through 3 are applied repeatedly between the result of the last join and the next table in the FROM clause until all tables are processed. WHERE: The WHERE filter is applied to VT3. Only rows for which the <where_condition> is TRUE are inserted to VT4. GROUP BY: The rows from VT4 are arranged in groups based on the column list specified in the GROUP BY clause. VT5 is generated. CUBE | ROLLUP: Supergroups (groups of groups) are added to the rows from VT5, generating VT6. HAVING: The HAVING filter is applied to VT6. Only groups for which the <having_condition> is TRUE are inserted to VT7. SELECT: The SELECT list is processed, generating VT8. DISTINCT: Duplicate rows are removed from VT8. VT9 is generated. ORDER BY: The rows from VT9 are sorted according to the column list specified in the ORDER BY clause. A cursor is generated (VC10). TOP: The specified number or percentage of rows is selected from the beginning of VC10. Table VT11 is generated and returned to the caller.



Therefore, (INNER JOIN) ON will filter the data (the data count of VT will be reduced here itself) before applying the WHERE clause. The subsequent join conditions will be executed with filtered data which improves performance. After that, only the WHERE condition will apply filter conditions.

(在ON / WHERE中应用条件语句在少数情况下不会有太大区别。这取决于你连接了多少个表,以及每个连接表中可用的行数)

其他回答

对于隐式连接,我有两点(第二个例子):

告诉数据库您想要什么,而不是它应该做什么。 您可以在一个清晰的列表中编写所有表,而不受连接条件的影响。这样你就可以更容易地阅读所有提到的表。所有的条件都出现在WHERE部分,它们也都是一个接一个地排列。使用JOIN关键字会混淆表和条件。

ANSI连接语法肯定更可移植。

我正在进行Microsoft SQL Server的升级,我还会提到,2005年SQL Server及以后的版本不支持外部连接的=*和*=语法(没有兼容模式)。

其他人指出INNER JOIN有助于人类的可读性,这是首要任务,我同意。 让我试着解释一下为什么联接语法可读性更强。

一个基本的SELECT查询如下:

SELECT stuff
FROM tables
WHERE conditions

SELECT子句告诉我们要返回什么;FROM子句告诉我们从哪里获取,where子句告诉我们从哪里获取。

JOIN是一个关于表以及它们如何绑定在一起的语句(从概念上讲,实际上是绑定到一个表中)。

控制表的任何查询元素——我们从中获取数据的地方——在语义上都属于from子句(当然,JOIN元素也在那里)。将连接元素放入WHERE子句中会合并which和WHERE -from,这就是为什么首选JOIN语法的原因。

SQL:2003标准更改了一些优先级规则,因此JOIN语句优先于“逗号”连接。这实际上可以改变查询的结果,这取决于它是如何设置的。当MySQL 5.0.12切换到遵循标准时,这对一些人造成了一些问题。

因此,在您的示例中,查询的工作原理是一样的。但是如果你添加第三个表: 选择……从table1, table2 JOIN table3 ON…在那里……

在MySQL 5.0.12之前,table1和table2先被连接,然后是table3。现在(5.0.12之后),table2和table3先被连接,然后是table1。它并不总是会改变结果,但它可以,而且你可能甚至没有意识到。

我不再使用“逗号”语法,选择你的第二个例子。无论如何,它都更具有可读性,JOIN条件是与JOIN一起的,而不是分离到单独的查询部分中。

我还将指出,使用旧语法更容易出错。如果使用不带ON子句的内部连接,则会出现语法错误。如果您使用旧的语法并且忘记了where子句中的一个连接条件,那么您将得到一个交叉连接。开发人员通常通过添加不同的关键字来解决这个问题(而不是修复连接,因为他们仍然没有意识到连接本身已经损坏),这可能看起来解决了问题,但会大大降低查询速度。

此外,对于维护,如果您在旧语法中有一个交叉连接,维护者如何知道您是否有意要有一个交叉连接(在需要交叉连接的情况下),或者这是一个应该修复的意外?

让我向您指出这个问题,看看为什么使用左连接时隐式语法不好。 Sybase *= Ansi标准与2个不同的外部表相同的内部表

另外,使用显式连接的标准已经超过20年了,这意味着隐式连接语法在这20年里已经过时了。你会使用已经过时20年的语法来编写应用程序代码吗?为什么要编写数据库代码呢?