You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SQL全外连接两种写法结果差异:Azure SQL DB中为何结果不同?

两种FULL OUTER JOIN查询结果不同的原因分析

这个问题的核心差异,在于JOIN的ON条件是匹配条件而非过滤条件,和子查询先过滤再JOIN的逻辑完全不一样,咱们一步步拆解来看:

第一个查询的执行逻辑

SELECT * FROM Table_A FULL OUTER JOIN Table_B ON (Table_A.Col1 = Table_B.Col1 AND Table_B.iscurrent=1)

这里的Table_B.iscurrent=1是写在JOIN的ON子句里的,它的作用是判断两行是否能匹配合并,而不是过滤Table_B的行。也就是说:

  • Table_B的所有行都会被保留在最终结果里:
    • 只有当Table_B的行满足iscurrent=1且Col1和Table_A的行匹配时,才会和Table_A的行合并成一行;
    • 对于Table_B中iscurrent≠1的行,不管Col1是否和Table_A匹配,因为不满足ON的匹配条件,都会单独作为一行出现在结果中,对应的Table_A列全部用NULL填充;
  • Table_A的所有行也会被保留:如果Table_A的行在Table_B中找不到iscurrent=1且Col1匹配的行,对应的Table_B列用NULL填充。

第二个查询的执行逻辑

SELECT * FROM Table_A FULL OUTER JOIN (Select * FROM Table_B Where iscurrent=1) AS Table_B ON (Table_A.Col1 = Table_B.Col1)

这里先通过子查询(Select * FROM Table_B Where iscurrent=1)对Table_B做了提前过滤,只保留iscurrent=1的行生成临时表,再和Table_A做FULL OUTER JOIN。这意味着:

  • Table_B中iscurrent≠1的行直接被排除,根本不会进入JOIN环节,自然不会出现在最终结果里;
  • 后续的JOIN逻辑只在Table_A和过滤后的Table_B子集之间进行,匹配规则就是Col1相等,不匹配的行用NULL填充。

举个实际例子更直观

假设:

  • Table_A有1行:(Col1=1, ColA='A1')
  • Table_B有2行:
    • (Col1=1, ColB='B1', iscurrent=0)
    • (Col1=2, ColB='B2', iscurrent=1)

第一个查询的结果会有3行:

  1. (1, 'A1', NULL, NULL, NULL) → Table_A的行,无匹配的Table_B行(因为Table_B中Col1=1的行iscurrent≠1)
  2. (NULL, NULL, 1, 'B1', 0) → Table_B中iscurrent=0的行,无匹配的Table_A行(不满足ON条件)
  3. (NULL, NULL, 2, 'B2', 1) → Table_B中iscurrent=1的行,无匹配的Table_A行

第二个查询的结果只有2行:

  1. (1, 'A1', NULL, NULL, NULL) → Table_A的行,无匹配的过滤后Table_B行
  2. (NULL, NULL, 2, 'B2', 1) → 过滤后的Table_B行,无匹配的Table_A行

总结差异根源

两个查询的核心区别就是:

  • 第一个查询会保留Table_B的所有行,哪怕是iscurrent≠1的行,只是这些行无法和Table_A的行匹配,会以NULL填充Table_A列的形式单独存在;
  • 第二个查询会提前剔除Table_B中iscurrent≠1的行,最终结果里完全看不到这些行。

内容的提问来源于stack exchange,提问作者Michael Bremen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 04:32:42