协慌网

登录 贡献 社区

INNER JOIN ON vs WHERE 子句

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

答案

INNER JOIN是您应该使用的 ANSI 语法。

它通常被认为更具可读性,尤其是当您加入大量表时。

只要有需要,它也可以很容易地用OUTER JOIN替换。

WHERE语法是面向关系模型的更多。

两个表JOIN ed 的结果是应用了过滤器的表的笛卡尔积,其仅选择具有匹配的连接列的那些行。

使用WHERE语法更容易看到这一点。

至于你的例子,在 MySQL(以及一般的 SQL)中,这两个查询是同义词。

另请注意,MySQL 也有一个STRAIGHT_JOIN子句。

使用此子句,您可以控制JOIN顺序:在外部循环中扫描哪个表以及在内部循环中扫描哪个表。

您无法使用WHERE语法在 MySQL 中控制此操作。

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

一个基本的 SELECT 查询是这样的:

SELECT stuff
FROM tables
WHERE conditions

SELECT 子句告诉我们, 正是我们找回; FROM 子句告诉我们从哪里获取它,WHERE 子句告诉我们我们得到了哪些

JOIN 是关于表的声明,它们如何绑定在一起(概念上,实际上,绑定到单个表中)。任何控制表的查询元素 - 我们从中获取东西 - 在语义上属于 FROM 子句(当然,这是 JOIN 元素所在的位置)。将 join-elements 放入 WHERE 子句会将whichwhere-from混合在一起; 这就是 JOIN 语法首选的原因。

在 ON / WHERE 中应用条件语句

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


参考:内部 Microsoft®SQLServer™2005 T-SQL 查询
出版商:微软出版社
发布日期:2006 年 3 月 7 日
打印 ISBN-10:0-7356-2313-9
打印 ISBN-13:978-0-7356-2313-2
页数:640

内部 Microsoft®SQLServer™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 子句几乎是最后处理的。

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

逻辑查询处理阶段简述

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

  1. FROM:在 FROM 子句的前两个表之间执行笛卡尔积(交叉连接),结果生成虚拟表 VT1。

  2. ON:ON 滤波器应用于 VT1。只有<join_condition>为 TRUE 的行才会插入 VT2。

  3. OUTER(join):如果指定了 OUTER JOIN(而不是 CROSS JOIN 或 INNER JOIN),则保留的表中未找到匹配项的行将作为外行添加到 VT2 的行中,从而生成 VT3。如果 FROM 子句中出现两个以上的表,则在最后一个连接的结果和 FROM 子句中的下一个表之间重复应用步骤 1 到步骤 3,直到处理完所有表。

  4. WHERE:WHERE 过滤器应用于 VT3。只有<where_condition>为 TRUE 的行才会插入 VT4。

  5. GROUP BY:VT4 中的行根据 GROUP BY 子句中指定的列列表按组排列。 VT5 已生成。

  6. CUBE | ROLLUP:超级组(组的组)被添加到 VT5 的行中,生成 VT6。

  7. HAVING:HAVING 过滤器应用于 VT6。只有<having_condition>为 TRUE 的组才会插入 VT7。

  8. SELECT:处理 SELECT 列表,生成 VT8。

  9. DISTINCT:从 VT8 中删除重复的行。生成 VT9。

  10. ORDER BY:VT9 中的行根据 ORDER BY 子句中指定的列列表进行排序。生成游标(VC10)。

  11. TOP:从 VC10 的开头选择指定的行数或百分比。生成表 VT11 并将其返回给调用者。



因此,(INNER JOIN)ON 将在应用 WHERE 子句之前过滤数据(此处 VT 的数据计数将减少)。随后的连接条件将使用过滤后的数据执行,从而提高性能。之后,只有 WHERE 条件才会应用过滤条件。

(在 ON / WHERE 中应用条件语句在少数情况下不会有太大区别。这取决于您加入的表数和每个连接表中可用的行数)