MySQL 将两个表中的记录与连接和不连接

Posted

技术标签:

【中文标题】MySQL 将两个表中的记录与连接和不连接【英文标题】:MySQL combining records from two tables with join and without 【发布时间】:2011-12-02 12:35:01 【问题描述】:

这两个查询有什么区别:

SELECT `threads`.`id` AS `threads.id` , `posts`.`id` , `posts`.`content`
FROM `threads`
JOIN `posts` ON `threads`.`id` = `posts`.`thread_id`

SELECT `threads`.`id` AS `threads.id` , `posts`.`id` , `posts`.`content`
FROM `threads` , `posts`
WHERE `threads`.`id` = `posts`.`thread_id`

它们都返回相同的数据。

【问题讨论】:

【参考方案1】:

WHERE子句过滤结果集是JOIN返回的,所以这是有区别的。

只要你使用INNER JOIN,无论是性能还是执行计划都没有差异,如果任何OUTER JOIN查询都会产生不同的执行计划。

还要注意mysql online doc里说的:

通常,您应该对指定条件使用 ON 子句 如何连接表,以及 WHERE 子句来限制哪些行 想要在结果集中。

【讨论】:

【参考方案2】:

一个使用 ANSI 连接,另一个使用 pre-ansi 样式连接。大多数数据库引擎会将它们编译成相同的执行计划。

【讨论】:

在 70 年代,当我开始使用 SQL 时,第二个是唯一可能的连接。然后 Chris Date “发明”了其他 JOINS,这就是引入新语法的地方。 是的;两者都工作正常。程序员的新面包被告知“正确”的方法是使用 ANSI。但是我发现通常都可以工作,而且有时 pre-ANSI 连接实际上会更快,反之亦然。我不知道为什么它们会生成具有不同性能的不同执行计划;但有时他们只是这样做。【参考方案3】:

一句话:可读性。

运行以下代码:

create table #threads (
id int
)

create table #posts (
id int,
thread_id int,
content varchar(10)
)

insert into #threads values (1)
insert into #threads values (2)
insert into #posts values (1, 1, 'Stack')
insert into #posts values (2, 2, 'OverFlow')


SELECT #threads.id AS 'threads.id' , #posts.id , #posts.content
FROM #threads
JOIN #posts ON #threads.id = #posts.thread_id

SELECT #threads.id AS 'threads.id' , #posts.id , #posts.content
FROM #threads, #posts
WHERE #threads.id = #posts.thread_id

drop table #threads
drop table #posts

在https://data.stackexchange.com/***/query/new 你会得到相同的执行计划:)

唯一真正的区别inner joinANSI,而from #threads, #postsTransact-SQL语法。

【讨论】:

【参考方案4】:

这些查询的内部实现可能有所不同,但我对此表示怀疑。 我个人更喜欢JOIN,因为它使执行计划更加明显。

【讨论】:

以上是关于MySQL 将两个表中的记录与连接和不连接的主要内容,如果未能解决你的问题,请参考以下文章

MySQL-表连接

一张图看懂Mysql的join连接

MySQL内连接(INNER JOIN)

两个 MySQL 表中的最佳连接

如何使用 MySQL 连接语句选择与链接表中的多个值匹配的记录?

左外连接不返回主表中的所有记录