你能有一个没有 ON 关键字的 INNER JOIN 吗?
Posted
技术标签:
【中文标题】你能有一个没有 ON 关键字的 INNER JOIN 吗?【英文标题】:Can you have an INNER JOIN without the ON keyword? 【发布时间】:2012-06-07 00:48:09 【问题描述】:在调试一些 Oracle 代码时,我遇到了这个查询:
SELECT TPM_TASK.TASKID FROM TPM_GROUP
INNER JOIN TPM_USERGROUPS ON TPM_GROUP.GROUPID = TPM_USERGROUPS.GROUPID
INNER JOIN TPM_TASK
INNER JOIN TPM_GROUPTASKS ON TPM_TASK.TASKID = TPM_GROUPTASKS.TASKID
INNER JOIN TPM_PROJECTVERSION ON TPM_TASK.PROJECTID = TPM_PROJECTVERSION.PROJECTID AND TPM_TASK.VERSIONID = TPM_PROJECTVERSION.VERSIONID
INNER JOIN TPM_TASKSTAGE ON TPM_TASK.STAGEID = TPM_TASKSTAGE.STAGEID
INNER JOIN TPM_PROJECTSTAGE ON TPM_PROJECTVERSION.STAGEID = TPM_PROJECTSTAGE.STAGEID
ON TPM_GROUP.GROUPID = TPM_GROUPTASKS.GROUPID
我被这条线弄糊涂了:
INNER JOIN TPM_TASK
我以前从未见过没有ON
子句的JOIN
。同样令人困惑的是这条线:
ON TPM_GROUP.GROUPID = TPM_GROUPTASKS.GROUPID
这似乎是一个随机的ON
子句,没有任何匹配的JOIN
。查询运行没有任何错误,并返回一堆数据,因此很明显语法是完全有效的。有人可以解释一下这里到底发生了什么吗?
【问题讨论】:
附带说明,如果有人正在搜索如何在没有 ON 子句的情况下创建连接(就像我一样),您可以使用“CROSS JOIN”来执行此操作,这将返回笛卡尔积。 【参考方案1】:小宇宙...我昨天遇到了一个生成这种语法的工具,很困惑。
显然,
FROM a
INNER JOIN b
INNER JOIN c ON (b.id = c.id)
ON (a.id = c.id)
相当于嵌套子查询
FROM a
INNER JOIN (SELECT <<list of columns>>
FROM b
INNER JOIN c ON (b.id=c.id)) c
ON (a.id = c.id)
【讨论】:
好吧,如果这个语法让伟大的 Justin Cave 感到困惑,那我肯定不会觉得太糟糕。我将在一些更简单的查询中使用它,以便我完全理解。谢谢! 你知道我已经盯着这个看很久了,但我无法理解。我认为我的困惑在于将c
用作表和子查询的别名。这是拼写错误还是典型用法?
@NeilBarnwell - 这不是错字。我相信我以这种方式构造了别名,因为原始查询中的c
既用作表,又用作子查询的别名。您可以使用别名为 d
的子查询和连接条件 a.id = d.id
编写相同的内容。
谢谢。我什至不知道你能做到这一点,因为它怎么知道你的意思是别名 c 或实际的表 c?我想有一个优先事项正在发生,我预计会出现某种模棱两可的引用错误。【参考方案2】:
我认为这只是查询排序的问题(因为只有INNER JOIN
s,它们的顺序并不那么重要)。我重新排列了您的查询,现在看起来像这样:
SELECT TPM_TASK.TASKID
FROM TPM_GROUP
INNER JOIN TPM_USERGROUPS
ON TPM_GROUP.GROUPID = TPM_USERGROUPS.GROUPID
INNER JOIN TPM_GROUPTASKS
ON TPM_GROUP.GROUPID = TPM_GROUPTASKS.GROUPID
INNER JOIN TPM_TASK
ON TPM_TASK.TASKID = TPM_GROUPTASKS.TASKID
INNER JOIN TPM_PROJECTVERSION
ON TPM_TASK.PROJECTID = TPM_PROJECTVERSION.PROJECTID
AND TPM_TASK.VERSIONID = TPM_PROJECTVERSION.VERSIONID
INNER JOIN TPM_TASKSTAGE
ON TPM_TASK.STAGEID = TPM_TASKSTAGE.STAGEID
INNER JOIN TPM_PROJECTSTAGE
ON TPM_PROJECTVERSION.STAGEID = TPM_PROJECTSTAGE.STAGEID
现在对你来说更有意义吗?对我来说更有意义。
【讨论】:
【参考方案3】:如果里面有括号就好了……
SELECT TPM_TASK.TASKID
FROM
TPM_GROUP
INNER JOIN TPM_USERGROUPS ON TPM_GROUP.GROUPID = TPM_USERGROUPS.GROUPID
INNER JOIN (
TPM_TASK
INNER JOIN TPM_GROUPTASKS ON TPM_TASK.TASKID = TPM_GROUPTASKS.TASKID
INNER JOIN TPM_PROJECTVERSION ON TPM_TASK.PROJECTID = TPM_PROJECTVERSION.PROJECTID
AND TPM_TASK.VERSIONID = TPM_PROJECTVERSION.VERSIONID
INNER JOIN TPM_TASKSTAGE ON TPM_TASK.STAGEID = TPM_TASKSTAGE.STAGEID
INNER JOIN TPM_PROJECTSTAGE ON TPM_PROJECTVERSION.STAGEID = TPM_PROJECTSTAGE.STAGEID
) ON TPM_GROUP.GROUPID = TPM_GROUPTASKS.GROUPID
但由于它们都是内部连接,我同意 Lamak 的回答。
【讨论】:
以上是关于你能有一个没有 ON 关键字的 INNER JOIN 吗?的主要内容,如果未能解决你的问题,请参考以下文章
SQL中的JOIN类型解释(CROSS, INNER,OUTER),关键字ON,USING
CROSS JOIN 是没有 ON 子句的 INNER JOIN 的同义词吗?
sql中 INNER JOIN LEFT JOIN RIGHT JOIN FULL JOIN 中 ON与Where的区别
sql中 INNER JOIN LEFT JOIN RIGHT JOIN FULL JOIN 中 ON与Where的区别