为简单起见,假设所有相关字段都为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中工作方式相同吗?


当前回答

一旦需要向查询中添加更多的表,隐式连接(第一个查询就是隐式连接)将变得更加混乱、难以阅读和维护。想象一下,在四五个不同的表上执行相同的查询和类型的连接……这是一场噩梦。

使用显式连接(第二个示例)可读性更强,也更容易维护。

其他回答

如果您经常编写动态存储过程,那么您会爱上第二个示例(使用where)。如果你有各种各样的输入参数和大量的变形混乱,那么这是唯一的方法。否则,它们将运行相同的查询计划,因此在经典查询中肯定没有明显的区别。

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

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

它们有不同的人类可读的含义。

但是,根据查询优化器的不同,它们对于机器可能具有相同的含义。

您应该始终使代码易于阅读。

也就是说,如果这是一个内置关系,则使用显式连接。如果匹配的是弱相关数据,则使用where子句。

隐式联接ANSI语法较旧,不太明显,不推荐使用。

此外,关系代数允许WHERE子句和INNER JOIN中的谓词互换性,因此即使使用WHERE子句的INNER JOIN查询也可以由优化器重新排列谓词。

我建议您以最易读的方式编写查询。

有时,这包括使INNER JOIN相对“不完整”,并将一些标准放在WHERE中,只是为了使过滤条件列表更容易维护。

例如,不要:

SELECT *
FROM Customers c
INNER JOIN CustomerAccounts ca
    ON ca.CustomerID = c.CustomerID
    AND c.State = 'NY'
INNER JOIN Accounts a
    ON ca.AccountID = a.AccountID
    AND a.Status = 1

写:

SELECT *
FROM Customers c
INNER JOIN CustomerAccounts ca
    ON ca.CustomerID = c.CustomerID
INNER JOIN Accounts a
    ON ca.AccountID = a.AccountID
WHERE c.State = 'NY'
    AND a.Status = 1

当然,这要视情况而定。

在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中应用条件语句在少数情况下不会有太大区别。这取决于你连接了多少个表,以及每个连接表中可用的行数)