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 始终遵循以下规则:

  1. 从联接的左侧获取所有行
  2. 从连接的右侧查找任何匹配的行,使用 ON ... 子句查找这些行。
  3. 根据从右侧找到的行数,执行以下操作:
    • 无行:在结果中从左侧生成一行,并使所有列都来自右侧 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.
  • 中的单行合并