你能有一个没有 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 JOINs,它们的顺序并不那么重要)。我重新排列了您的查询,现在看起来像这样:

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

26.MySQL中的内连接INNER JOIN

Sql inner join

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的区别