sql 加入 'on' 运算符未过滤
sql join 'on' operator not filtering
这可能是重复的,但我不知道如何正确搜索。我会写基本的 sql,并且知道概念 'Cartesian product'。但是我总是在某种程度上对 join 中的 on 感到困惑。 sql服务器中的示例:
A | B
--+--
1 | 2
2 | 3
select * from ta left join tb on ta.A = 2 --??!
A | B
--+--
1 | Null
2 | 2
2 | 3
select * from ta left join tb on tb.B = 2 --seems easier to understand
A | B
--+--
1 | 2
2 | 2
谁能解释第一个 sql(在 ta.A = 2),为什么 A 列没有被过滤。顺便说一下,我知道 on ta.ColA=tb.ColB 最常见的用法,但是在这个问题中我只想知道 on 是如何工作的。
在 LEFT JOIN
中,连接左侧的所有行将始终 保留。 ON
条件确定右侧的任何行是否会成功连接到这些行。
所以,
select * from ta left join tb on ta.A = 2 --??!
A | B
--+--
1 | Null
2 | 2
2 | 3
当 A
等于 1
时,条件 ta.A = 2
永远不会为真,因此 没有 行来自 tb
被保留。
当 A
等于 2
时,条件 ta.A = 2
为真,因此 所有 行来自 tb
连接到 ta
.
中的此类行
A LEFT JOIN
始终遵循以下规则:
- 从联接的左侧获取所有行
- 从连接的右侧查找任何匹配的行,使用
ON ...
子句查找这些行。
- 根据从右侧找到的行数,执行以下操作:
- 无行:在结果中从左侧生成一行,并使所有列都来自右侧
NULL
- 一行:将左侧的单行与右侧的单行合并
- 多行:将左侧的单行与右侧的每一行组合,在输出中产生多行
因此您的 ON TA.A=2
仅用于从右侧过滤行。
现在,你的问题中有一个错误,这让你更难理解问题所在。
这个输出:
A | B
--+--
1 | Null
1 | 2 <-- notice A=1 here, this is incorrect
2 | 3
应该是这样的:
A | B
--+--
1 | Null
2 | 2 <-- notice A=2 here
2 | 3
基本上,您的查询是这样的:
- 取
TA
中的所有行
- 从
TB
中查找行,其中 TA.A=2
为真,这只会在您位于 A=2
行时发生,这就是为什么您有 Null
A=1
.
- 由于您没有指定需要
TB
行中的哪一行,因此所有这些行都将与 A=2
. 中的单行合并
这可能是重复的,但我不知道如何正确搜索。我会写基本的 sql,并且知道概念 'Cartesian product'。但是我总是在某种程度上对 join 中的 on 感到困惑。 sql服务器中的示例:
A | B
--+--
1 | 2
2 | 3
select * from ta left join tb on ta.A = 2 --??!
A | B
--+--
1 | Null
2 | 2
2 | 3
select * from ta left join tb on tb.B = 2 --seems easier to understand
A | B
--+--
1 | 2
2 | 2
谁能解释第一个 sql(在 ta.A = 2),为什么 A 列没有被过滤。顺便说一下,我知道 on ta.ColA=tb.ColB 最常见的用法,但是在这个问题中我只想知道 on 是如何工作的。
在 LEFT JOIN
中,连接左侧的所有行将始终 保留。 ON
条件确定右侧的任何行是否会成功连接到这些行。
所以,
select * from ta left join tb on ta.A = 2 --??!
A | B
--+--
1 | Null
2 | 2
2 | 3
当 A
等于 1
时,条件 ta.A = 2
永远不会为真,因此 没有 行来自 tb
被保留。
当 A
等于 2
时,条件 ta.A = 2
为真,因此 所有 行来自 tb
连接到 ta
.
A LEFT JOIN
始终遵循以下规则:
- 从联接的左侧获取所有行
- 从连接的右侧查找任何匹配的行,使用
ON ...
子句查找这些行。 - 根据从右侧找到的行数,执行以下操作:
- 无行:在结果中从左侧生成一行,并使所有列都来自右侧
NULL
- 一行:将左侧的单行与右侧的单行合并
- 多行:将左侧的单行与右侧的每一行组合,在输出中产生多行
- 无行:在结果中从左侧生成一行,并使所有列都来自右侧
因此您的 ON TA.A=2
仅用于从右侧过滤行。
现在,你的问题中有一个错误,这让你更难理解问题所在。
这个输出:
A | B
--+--
1 | Null
1 | 2 <-- notice A=1 here, this is incorrect
2 | 3
应该是这样的:
A | B
--+--
1 | Null
2 | 2 <-- notice A=2 here
2 | 3
基本上,您的查询是这样的:
- 取
TA
中的所有行
- 从
TB
中查找行,其中TA.A=2
为真,这只会在您位于A=2
行时发生,这就是为什么您有Null
A=1
. - 由于您没有指定需要
TB
行中的哪一行,因此所有这些行都将与A=2
. 中的单行合并