sql join' on'运算符不过滤

时间:2016-01-15 07:45:16

标签: sql sql-server join left-join

这可能是重复但我不知道如何正确搜索。我可以编写基本的sql,并且知道概念'笛卡尔积['但我总是在某种程度上对联接中的 感到困惑。 sqlserver中的示例:

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( on ta.A = 2 ),为什么A列未被过滤。顺便说一句,我知道最常用的ta.ColA = tb.ColB,但在这个问题中,我只是想知道 on 是如何工作的。

2 个答案:

答案 0 :(得分:3)

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中的 no 行。< / p>

A等于2时,条件ta.A = 2为真,因此来自tb所有行都会加到这些行中在ta

答案 1 :(得分:3)

LEFT JOIN始终遵循以下规则:

  1. 从联接的左侧获取所有行
  2. 使用ON ...子句查找连接右侧的所有匹配行,以查找这些行。
  3. 根据从右侧找到的行数,执行以下操作:
    • 没有行:在结果中从左侧生成一行,并使所有列都来自右侧NULL
    • 一行:将左侧的单行与右侧的单行组合
    • 多行:将左侧的单行与右侧的每一行合并,在输出中生成多行
  4. 因此,您的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中的单行合并。