正常的JOIN … ON …语法是众所周知的.但是也可以将ON子句与它对应的JOIN分开定位.这是在实践中很少见到的东西,在教程中找不到,我没有发现任何网络资源甚至提到这是可能的.
这是一个可以玩的脚本:
SELECT * INTO #widgets1 FROM (VALUES (1),(2),(3)) x(WidgetID) SELECT * INTO #widgets2 FROM (VALUES (1,'SomeValue1'),(2,'SomeValue2'),(3,'SomeValue3')) x(WidgetID,SomeValue) SELECT * INTO #widgetProperties FROM (VALUES (1,'a'),(1,'b'),'b')) x(WidgetID,PropertyName) --q1 SELECT w1.WidgetID,w2.SomeValue,wp.PropertyName FROM #widgets1 w1 LEFT JOIN #widgets2 w2 ON w2.WidgetID = w1.WidgetID LEFT JOIN #widgetProperties wp ON w2.WidgetID = wp.WidgetID AND wp.PropertyName = 'b' ORDER BY w1.WidgetID --q2 SELECT w1.WidgetID,wp.PropertyName FROM #widgets1 w1 LEFT JOIN #widgets2 w2 --no ON clause here JOIN #widgetProperties wp ON w2.WidgetID = wp.WidgetID AND wp.PropertyName = 'b' ON w2.WidgetID = w1.WidgetID ORDER BY w1.WidgetID --q3 SELECT w1.WidgetID,wp.PropertyName FROM #widgets1 w1 LEFT JOIN ( #widgets2 w2 --no SELECT or FROM here JOIN #widgetProperties wp ON w2.WidgetID = wp.WidgetID AND wp.PropertyName = 'b') ON w2.WidgetID = w1.WidgetID ORDER BY w1.WidgetID
q1看起来很正常. q2和q3具有ON子句的这些不寻常的定位.
这个脚本不一定有意义.我很难设计一个有意义的场景.
那么这些不寻常的语法模式意味着什么?这是如何定义的?我注意到并非所有两个ON子句的位置和顺序都是允许的.管理这个的规则是什么?
写这样的查询也是个好主意吗?
解决方法
如果你看一下
FROM
clause syntax diagram,你会发现ON子句只有一个地方:
<joined_table> ::= { <table_source> <join_type> <table_source> ON <search_condition> ... }
你觉得令人困惑的是简单的递归,因为< table_source>在< joined_table>中上面可以是另一个< joined_table>:
[ FROM { <table_source> } [,...n ] ] <table_source> ::= { table_or_view_name ... ... | <joined_table> ... }
为了避免混淆,你应该在非显而易见的情况下使用括号(比如你的例子)在视觉上分开< table_sources> ;;它们对于查询解析器不是必需的,但对人类有用.