问题 MySql JOINS的优点/缺点


当我从多个表中选择数据时,我常常使用JOINS,最近我开始使用另一种方式,但从长远来看,我不确定其影响。

例子:

SELECT * FROM table_1 LEFT JOIN table_2 ON (table_1.column = table_2.column)

所以这是跨表的基本LEFT JOIN,但请看下面的查询。

SELECT * FROM table_1,table_2 WHERE table_1.column = table_2.column

就个人而言,如果我加入,请说7个数据表我宁愿在JOINS上这样做。

但是这两种方法有什么优缺点吗?


6550
2017-08-29 16:16


起源



答案:


第二种方法是INNER JOIN的快捷方式。

 SELECT * FROM table_1 INNER JOIN table_2 ON table_1.column = table_2.column

只会选择与两个表中的条件匹配的记录(LEFT JOIN将从左侧的表中选择所有记录,并从右侧的表中选择匹配的记录)

引用自 http://dev.mysql.com/doc/refman/5.0/en/join.html

[...]我们将table_reference项列表中的每个逗号视为等同于内连接

在没有连接条件的情况下,INNER JOIN和(逗号)在语义上是等价的:两者在指定的表之间产生笛卡尔积(即,第一个表中的每一行都连接到第二个表中的每一行)。

但是,逗号运算符的优先级小于INNER JOIN,CROSS JOIN,LEFT JOIN等。如果在存在连接条件时将逗号连接与其他连接类型混合,则可能会出现'on子句'中未知列'col_name'形式的错误。有关处理此问题的信息将在本节后面给出。

一般来说,有很多提到的东西,应该让你考虑不使用逗号。


10
2017-08-29 16:19



令人惊讶的是MySQL将它们视为内部联接和交叉联接。我可以理解为什么,但是哇他们并没有因为偏离标准而给MySQL开发人员带来任何好处。 - Thomas
@Thomas:你错过了“没有加入条件”。 - OMG Ponies
@OMG小马 - 我相信它仍然是非标准的。你能想象一下在Where子句中有十几个表和许多其他过滤语句的大型查询,试图找到将内连接转换为交叉连接的缺失连接条件吗?的Bleh。 ON子句的语法要求肯定有助于那里的开发人员。 - Thomas
@Thomas:对我来说,这一切都是ANSI-92语法。我不得不克制自己习惯性地转换ANSI-89语法:) - OMG Ponies
我记得1991年在学校里做了快捷方法。实际上我不相信RDBMS支持INNER JOIN tbl ON ...语法。 - FastAl


答案:


第二种方法是INNER JOIN的快捷方式。

 SELECT * FROM table_1 INNER JOIN table_2 ON table_1.column = table_2.column

只会选择与两个表中的条件匹配的记录(LEFT JOIN将从左侧的表中选择所有记录,并从右侧的表中选择匹配的记录)

引用自 http://dev.mysql.com/doc/refman/5.0/en/join.html

[...]我们将table_reference项列表中的每个逗号视为等同于内连接

在没有连接条件的情况下,INNER JOIN和(逗号)在语义上是等价的:两者在指定的表之间产生笛卡尔积(即,第一个表中的每一行都连接到第二个表中的每一行)。

但是,逗号运算符的优先级小于INNER JOIN,CROSS JOIN,LEFT JOIN等。如果在存在连接条件时将逗号连接与其他连接类型混合,则可能会出现'on子句'中未知列'col_name'形式的错误。有关处理此问题的信息将在本节后面给出。

一般来说,有很多提到的东西,应该让你考虑不使用逗号。


10
2017-08-29 16:19



令人惊讶的是MySQL将它们视为内部联接和交叉联接。我可以理解为什么,但是哇他们并没有因为偏离标准而给MySQL开发人员带来任何好处。 - Thomas
@Thomas:你错过了“没有加入条件”。 - OMG Ponies
@OMG小马 - 我相信它仍然是非标准的。你能想象一下在Where子句中有十几个表和许多其他过滤语句的大型查询,试图找到将内连接转换为交叉连接的缺失连接条件吗?的Bleh。 ON子句的语法要求肯定有助于那里的开发人员。 - Thomas
@Thomas:对我来说,这一切都是ANSI-92语法。我不得不克制自己习惯性地转换ANSI-89语法:) - OMG Ponies
我记得1991年在学校里做了快捷方法。实际上我不相信RDBMS支持INNER JOIN tbl ON ...语法。 - FastAl


第一种方法是Join的ANSI / ISO版本。第二种方法是旧格式(pre-89),以产生内部连接的等价物。它通过交叉连接您列出的所有表,然后在Where子句中缩小笛卡尔积来生成等效的内连接。

我强烈建议不要使用第二种方法。

  1. 其他开发人员更难阅读
  2. 它打破了其他开发人员最不惊讶的规则,他们会怀疑你是否只是不知道更好,或者是否有某些特定原因不使用ANSI / ISO格式。
  3. 当你开始尝试使用除内连接之外的其他格式时,它会让你感到悲伤。
  4. 这使得识别您的意图变得更加困难,尤其是在具有许多表的大型查询中。所有这些表都应该是内连接吗?您是否错过了Where子句中的某些内容并创建了交叉连接?你打算交叉加入吗?等等。

没有理由使用第二种格式,事实上许多数据库系统正在终止对该格式的支持。


3
2017-08-29 16:45





ANSI语法

两个查询都是JOIN,并且都使用ANSI语法,但一个比另一个查询旧。

加入使用 JOIN keyword表示正在使用ANSI-92语法。 ANSI-89语法是指在表中以逗号分隔的表 FROM子句,以及加入它们的标准可以在 WHERE 条款。比较INNER JOIN时,没有性能差异 - 这个:

SELECT * 
  FROM table_1 t1, table_2 t2
 WHERE t1.column = t2.column

...将生成相同的查询计划:

SELECT *
  FROM TABLE_1 t1
  JOIN TABLE_2 t2 ON t2.column = t1.column

苹果到橘子

另一个区别是两个查询不相同 - LEFT [OUTER] JOIN将生成所有行 TABLE_1和参考 TABLE_2 如果根据JOIN条件(在。中指定)没有匹配,则在输出中将为NULL ON 条款)。第二个例子是INNER JOIN,它会 只要 生成具有匹配记录的行 TABLE_2。这是一个 链接到JOIN的可视化表示 加强差异......

优点缺点

使用ANSI-92语法的主要原因是因为ANSI-89没有任何OUTER JOIN(LEFT,RIGHT,FULL)支持。 ANSI-92语法是专门为解决这个缺点而引入的,因为供应商正在实现他们自己的自定义语法。 Oracle使用过 (+); SQL Server在连接条件中使用等号旁边的星号(IE: t1.column =* t2.column)。

使用ANSI-92语法的下一个原因是它更明确,更具可读性,同时将用于连接表的内容与实际过滤分开。


2
2017-08-29 17:02





我个人觉得显式连接语法(A JOIN BA LEFT JOIN B)是优选的。两者都是因为它更清楚你正在做什么,并且因为如果你对内部联接使用隐式连接语法,你仍然必须使用外部联接的显式语法,因此你的SQL格式将是不一致的。


0
2017-08-29 16:38





我同意Mchl和Thomas在答案中所写的内容。我特别强调你应该避免使用第二个例子(你通过它指定连接的地方) WHERE 条款)并且更明确 JOIN ... ON 形成。

我正在争论这个因为显式版本(LEFT JOIN ... ON ... = ...)有另一个重要的优点:你有明确分开的连接规范(在 JOIN ... ON 从实际过滤条件(在 WHERE ()),使您的SQL代码更清晰,更易于理解。


0
2017-08-29 16:53