正常的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'),
(2, 'a'), (2, '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, w2.SomeValue, 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, w2.SomeValue, 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
Run Code Online (Sandbox Code Playgroud)
q1 看起来正常。q2 和 q3 有这些不寻常的ON子句定位。
这个脚本不一定有多大意义。我很难设计一个有意义的场景。
那么这些不寻常的语法模式是什么意思呢?这是如何定义的?我注意到并非这两个ON子句的所有位置和顺序都是允许的。对此有何规定?
编写这样的查询也是一个好主意吗?
Mar*_*ith 33
它确定连接中涉及的逻辑表。
举个简单的例子
SELECT w1.WidgetID,
w2.SomeValue,
wp.PropertyName
FROM #widgets1 w1
LEFT JOIN #widgets2 w2
ON w2.WidgetID = w1.WidgetID
JOIN #widgetProperties wp
ON w2.WidgetID = wp.WidgetID
AND wp.PropertyName = 'b'
ORDER BY w1.WidgetID
Run Code Online (Sandbox Code Playgroud)
#widgets1左外连接#widgets2- 其结果形成了一个内连接到的虚拟表#widgetProperties。谓词w2.WidgetID = wp.WidgetID意味着过滤掉来自初始外连接的任何空扩展行,从而有效地使所有连接成为内连接。
这与 q2 不同...
SELECT w1.WidgetID,
w2.SomeValue,
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
Run Code Online (Sandbox Code Playgroud)
#widgets2是内部连接到#widgetProperties. 由该连接产生的虚拟表然后是左外部连接中的右侧表#widgets1
使用派生表或公用表表达式可以实现相同的结果...
WITH VT2
AS (SELECT w2.WidgetID,
w2.SomeValue,
wp.PropertyName
FROM #widgets2 w2
JOIN #widgetProperties wp
ON w2.WidgetID = wp.WidgetID
AND wp.PropertyName = 'b')
SELECT w1.WidgetID,
VT2.SomeValue,
VT2.PropertyName
FROM #widgets1 w1
LEFT JOIN VT2
ON VT2.WidgetID = w1.WidgetID
ORDER BY w1.WidgetID
Run Code Online (Sandbox Code Playgroud)
... 或者,您可以重新排序虚拟表并使用 aRIGHT JOIN代替。
SELECT w1.WidgetID,
w2.SomeValue,
wp.PropertyName
FROM #widgets2 w2
INNER JOIN #widgetProperties wp
ON w2.WidgetID = wp.WidgetID
AND wp.PropertyName = 'b'
RIGHT JOIN #widgets1 w1
ON w2.WidgetID = w1.WidgetID
ORDER BY w1.WidgetID
Run Code Online (Sandbox Code Playgroud)
... JOIN 条件必须遵循与表顺序的 chiastic 关系。也就是说,如果按该顺序指定表 T1、T2、T3 和 T4,并且 JOIN 条件匹配 T1 与 T2、T2 与 T3、T3 与 T4,则必须以与表顺序相反的顺序指定 JOIN 条件, 像这样:
FROM T1
<join_type> T2 T2
<join_type> T3 T3
<join_type> T4
ON T4.key = T3.key
ON T3.key = T2.key
ON T2.key = T1.key
Run Code Online (Sandbox Code Playgroud)
以不同的方式看待这种连接技术,给定的 JOIN 条件只能引用它上面的表名或早期 JOIN 条件已经引用和解析的表名。
但这篇文章有许多不准确之处,请参阅Lubor Kollar的后续信件。
mus*_*cio 32
如果您查看FROM子句语法图,您会发现该ON子句只有一处:
<joined_table> ::=
{
<table_source> <join_type> <table_source> ON <search_condition>
...
}
Run Code Online (Sandbox Code Playgroud)
你会感到困惑的是简单的递归,因为<table_source>在<joined_table> 上面可以是另一个<joined_table>:
[ FROM { <table_source> } [ ,...n ] ]
<table_source> ::=
{
table_or_view_name ...
...
| <joined_table>
...
}
Run Code Online (Sandbox Code Playgroud)
为避免混淆,您应该在不明显的情况下(如您的示例)使用括号在视觉上分开<table_sources>;它们对于查询解析器不是必需的,但对人类有用。
| 归档时间: |
|
| 查看次数: |
2283 次 |
| 最近记录: |