View 的 ON 子句与 JOIN 不按顺序出现

Posted

技术标签:

【中文标题】View 的 ON 子句与 JOIN 不按顺序出现【英文标题】:ON clauses of View do not appear in order with JOINs 【发布时间】:2014-08-22 22:44:34 【问题描述】:

在 SSMS 2012 中,我正在查看在 MS Access 中创建的大视图。当我将视图编写到查询窗口时,FROM 子句如下所示:

FROM         dbo.oa_projecttask_type RIGHT OUTER JOIN
    dbo.oa_project_task RIGHT OUTER JOIN
    dbo.[Functional Area] RIGHT OUTER JOIN
    dbo.oa_category ON dbo.[Functional Area].[Product Code] = dbo.oa_category.name RIGHT OUTER JOIN
    dbo.oa_project RIGHT OUTER JOIN
    dbo.vw_People_All_Ever RIGHT OUTER JOIN
    dbo.oa_task ON dbo.vw_People_All_Ever.[User ID] = dbo.oa_task.user_id ON dbo.oa_project.id = dbo.oa_task.project_id ON 
    dbo.oa_category.id = dbo.oa_task.category_id ON dbo.oa_project_task.id = dbo.oa_task.project_task_id ON 
    dbo.oa_projecttask_type.id = dbo.oa_task.projecttask_type_id LEFT OUTER JOIN
    dbo.upl_approval_status RIGHT OUTER JOIN
    dbo.oa_timesheet ON dbo.upl_approval_status.Code = dbo.oa_timesheet.status ON dbo.oa_task.timesheet_id = dbo.oa_timesheet.id
WHERE     (CONVERT(datetime, oa_task.created) > GETDATE() - 366) AND (oa_task.deleted IS NULL)

当我格式化子句时,JOIN 和 ON 在不同的行上,它看起来像这样:

FROM oa_projecttask_type 
   RIGHT OUTER JOIN oa_project_task 
   RIGHT OUTER JOIN [Functional Area] 
   RIGHT OUTER JOIN oa_category 
      ON [Functional Area].[Product Code] = oa_category.name 
   RIGHT OUTER JOIN oa_project 
   RIGHT OUTER JOIN vw_People_All_Ever 
   RIGHT OUTER JOIN oa_task 
      ON vw_People_All_Ever.[User ID] = oa_task.user_id 
      ON oa_project.id = oa_task.project_id 
      ON oa_category.id = oa_task.category_id 
      ON oa_project_task.id = oa_task.project_task_id 
      ON oa_projecttask_type.id = oa_task.projecttask_type_id 
   LEFT OUTER JOIN upl_approval_status 
   RIGHT OUTER JOIN oa_timesheet 
      ON upl_approval_status.Code = oa_timesheet.status 
      ON oa_task.timesheet_id = oa_timesheet.id
WHERE     (CONVERT(datetime, oa_task.created) > GETDATE() - 366) AND (oa_task.deleted IS NULL)

许多 JOIN 没有 ON 语句,但视图编译并返回数据没有错误。没有 ON 子句的 RIGHT OUTER JOIN 是什么意思——它是笛卡尔连接吗?

更新:基于这个问题 -- Wierd SQL Server view definition -- 及其链接,我们不能简单地将 JOIN/ON 重新排列为更合理的顺序 -- 顺序会影响检索的逻辑。我只是用更容易理解的逻辑重写这个查询。感谢@MartinSmith 和所有人!

【问题讨论】:

on 子句的位置控制逻辑连接顺序和参与连接的虚拟表。我懒得重写你冗长的查询,但你需要的所有信息都可以在这个答案的链接中找到。 ***.com/a/7312901/73226 【参考方案1】:

如果您仔细检查,您会发现每个 Right Outer Join 都有他的 ON 语句,只是不在该位置。 我想所有joins 都会找到自己的ONs,因为ON 需要ON 语句才能正常工作。

有关此主题的更多信息,您可以在 cmets 中找到 HERE Martin Smith。

【讨论】:

on 子句的位置控制逻辑连接顺序并更改语义。你可以在这里看到一个简单的例子。 ***.com/a/7313507/73226 好吧,我想就目前而言,但错过了最重要的一点,即它改变了参与连接的虚拟表。 @MartinSmith 这没什么大不了的,但我不同意您将其标记为重复。虽然您的链接问题是对连接的非常简单的解释,但绝对 no 提到 WHERE 子句中以 any 顺序出现的 ON,这是 SQL Server 的一个令人惊讶的功能...另外,在我对问题的澄清编辑中还有进一步的问题。 @user906802 这个问题是重复的。诚然,我的回答并没有做太多解释。您真的需要阅读其中的链接。从 Itzik 开始,但其中包含在后续文章中更正的一些错误。具体来说,当只需要放置 on 子句时,原始文章看起来好像需要括号。 @MartinSmith 感谢您的快速回复。我们可以同意不同意...但是上帝帮助可怜的 SQL 家伙,他必须处理 Access 生成的代码!但是我在右连接问题中找不到“Itzik”链接——我只找到 2 个链接,一个指向 Susan Harkins 帖子,另一个指向 mysql 文档页面。你确定你发布了正确的参考吗? This 链接在此问题的重复标题中短暂出现,似乎相当相关。

以上是关于View 的 ON 子句与 JOIN 不按顺序出现的主要内容,如果未能解决你的问题,请参考以下文章

使用 JOIN 时的 WHERE 子句与 ON

LINQ Join 与 On 子句中的多个条件

Oracle SQL - FROM 子句中的 JOIN 顺序会影响性能优化吗?

将索引与 where 和 join 子句一起使用

PostgreSQL 中的 SQL JOIN - WHERE 子句中的执行计划与 ON 子句中的不同

【Hive】Hive Join 介绍