【问题标题】:SQL INNER JOIN implemented as implicit JOINSQL INNER JOIN 实现为隐式 JOIN
【发布时间】:2014-11-16 13:44:10
【问题描述】:

最近,我遇到了一个如下所示的 SQL 查询:

SELECT * FROM A, B WHERE A.NUM = B.NUM

在我看来,这似乎与 INNER JOIN 的返回完全相同:

SELECT * FROM A INNER JOIN B ON A.NUM = B.NUM

有什么理智的理由为什么有人会在这里使用CROSS JOIN?编辑:似乎大多数 SQL 应用程序都会在这里自动使用INNER JOIN

数据库是HSQLDB

【问题讨论】:

  • 第一个不是CROSS JOIN,它是INNER JOIN 的旧形式,在WHERE 中具有连接条件。查询是一样的。
  • 能否请您指定您使用的 RDBMS,这样我们就不必猜测了?
  • 不,没有任何理智的人会在这里使用 CROSS JOIN 的理由。 CROSS JOIN 意味着您想要一个笛卡尔积 - 虽然可以强制它表现得像带有额外过滤器的 INNER JOIN,但我不明白这一点。当你想要一个 INNER JOIN 时,使用 INNER JOIN;当你想要一个 CROSS JOIN 时,使用 CROSS JOIN。不管开源文档怎么说,或者 MySQL 多么想偏离 SQL 标准。我可以在很多没有明确禁止非机动车行驶的高速公路上骑三轮车,但这并不意味着这样做是理智或合乎逻辑的。

标签: sql inner-join hsqldb cross-join


【解决方案1】:

是的,您的两个语句将返回相同的结果。使用哪一个是口味问题。如果可能,每个健全的数据库系统都会对两者都使用连接,没有健全的优化器会在第一种情况下真正使用叉积。

但请注意,您的第一个语法不是交叉连接。它只是一个隐含的连接符号,它没有指定使用哪种连接。相反,优化器必须检查WHERE 子句以确定是使用内连接还是交叉连接:如果在WHERE 子句中找到适用的连接条件,这将导致内连接。如果没有找到这样的子句,它将导致交叉连接。由于您的第一个示例指定了一个适用的连接条件 (WHERE A.NUM = B.NUM),这将导致 INNER JOIN,因此与您的第二个示例完全相同。

【讨论】:

  • +1。在 OP 示例中有人将关键字“INNER”替换为“CROSS”的唯一“理智”原因是他们使用的是 MySQL,并且他们知道 在 MySQL “JOIN”、“INNER JOIN”和“CROSS JOIN”是同义词。
  • @spencer7593 我不明白为什么一个理智的人会用 CROSS 替换 INNER,即使在极少数情况下它们是相同的。它们可以用于不同的目的,那么为什么不将它们分开而不是提倡你互换它们呢? Yosemite Sam 可能对 MySQL 中允许在没有 ON 子句的情况下进行 INNER JOIN 的故障负责这一事实不是借口。而且,如果 OP 甚至使用 MySQL,我们仍然有 NO IDEA
  • 我必须同意CROSS JOIN 的 MySQL 语义相当奇怪。即使在 MySQL 中是可能的,我也会避免写 CROSS JOIN 用于不意味着是真正的交叉产品的连接。这会混淆查询的含义,并使不熟悉 MySQL 的读者发疯。
  • 不,这不是品味问题。隐式连接是已知的 SQL 反模式。它们通常会导致显式连接(例如意外交叉连接)无法解决的问题。隐式连接在 20 多年前被替换,现在是完全停止使用它们的时候了。
【解决方案2】:

较旧的语法是 SQL 反模式。每当您看到它时,都应该将其替换为内部连接。它是反模式的部分原因是,如果省略 where 子句,则无法判断交叉连接是否是有意的。这会导致许多意外的交叉连接,尤其是在复杂的查询中。此外,在某些数据库(尤其是 Sql 服务器)中,隐式外连接无法正常工作,因此人们试图将显式连接和隐式连接结合起来,并在没有意识到的情况下得到不好的结果。总而言之,即使考虑使用隐式连接也是一种糟糕的做法。

【讨论】:

  • 有充分的理由表明JOIN 关键字优于旧式逗号语法用于连接操作。最大的原因之一是使用逗号语法编写的“错误”SQL,更难找出错误所在。通过在 ON 子句中适当使用 JOIN 关键字和连接谓词,可以更轻松地发现 SQL 语句的问题。 Joel 没有在他十年前的博文中专门讨论 SQL:Making wrong code look wrong,但我认为同样的原则也适用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-03-09
  • 2013-07-01
  • 2013-07-19
  • 1970-01-01
  • 2020-02-08
  • 2016-04-28
  • 2015-01-10
相关资源
最近更新 更多