【问题标题】:difference between these sql joins (same results, same exec plans)这些 sql 连接之间的区别(相同的结果,相同的执行计划)
【发布时间】:2016-06-15 10:27:51
【问题描述】:

两张桌子。第一个表包含每个人,另一个表用于指定哪个人是家庭成员中的孩子:

create table persons(
    personID bigint primary key auto_increment,
    firstName varchar(30) not null,
    lastName varchar(30) not null
);

create table kids(
    personID bigint not null,
    familyID bigint not null,
    grade bigint,

    constraint kidReference foreign key (personID) references persons (personID),
    constraint familyReference foreign key (familyID) references families (familyID)
);

我想为每个孩子选择所有详细信息。使用以下查询,我得到相同的结果,相同的 相同 执行计划:

(1) 逗号分隔连接:

select persons.personID, persons.firstName, persons.lastName, kids.familyID, kids.grade from persons, kids where persons.personID = kids.personID;

(2)自然连接:

select * from persons natural join kids;

(3)命名连接:

select * from persons join kids using (personID);

(4)条件连接:

select * from persons inner join kids on persons.personID = kids.personID;

这仅仅是可读性的问题吗?在编写查询时,我应该只针对 -what-it-works-best-?

【问题讨论】:

  • 您应该避免在from 子句中使用逗号(这是由更强大的join/on 子句取代的古老语法)和natural join(等待发生的错误)。否则,请为手头的问题和您最熟悉的语法选择适当的连接。

标签: mysql sql join inner-join natural-join


【解决方案1】:

在您的情况下,查询的每个版本都会产生相同的基本查询。

逗号语法将尝试根据 WHERE 子句查找连接。 where persons.personID = kids.personID 变为 inner join kids on persons.personID = kids.personID。请注意,= 导致内连接,*= 导致左连接。

自然连接看起来连接具有相同名称的列,即PersonID。您无需指定特定名称,因为自然连接会为您找到常用名称。默认是内连接。

命名连接using (PersonID) 是在列名PersonID 上连接两个表的简写,它们都共享。 JOIN 本身被解释为内部连接。

最终版本准确地说明了您想要的内容,无需解释。

我更喜欢最终版本,因为它没有惊喜。

话虽如此,JOIN using (personID) 也是明确的 - 它只是最终版本的简写。

【讨论】:

  • 很好的答案,只有两件事:1) 避免使用旧式连接(第一个版本),它自 1992 年以来已被弃用。2)第4种是标准中规定的一种,第2种和第3种不被其他RDMBS支持。
  • @Pred 这些都是好点。@hrs 小心natural join,正如 Gordon Linoff 所说。例如,两个表可能都将列id 作为主键,每个新行递增1。在 id 的幕后加入纯粹基于名称,在逻辑上是错误的。
猜你喜欢
  • 1970-01-01
  • 2010-11-08
  • 1970-01-01
  • 1970-01-01
  • 2017-01-10
  • 1970-01-01
  • 2011-08-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多