Oracle查询执行顺序:LEFT JOIN与WHERE子句的执行先后问题
Oracle中LEFT JOIN与WHERE子句的执行顺序解答
结论
Oracle SQL的逻辑执行顺序是先完成LEFT JOIN关联,再执行WHERE子句过滤。优化器可能会做不改变语义的物理执行优化(比如谓词下推),但不会改变SQL本身的执行逻辑。
测试数据说明
表A
COL_A ----- 1 2 3 4
表B
COL_B ----- 1 2 3 5
执行SQL
select a.col_a, b.col_b from a left join b on a.col_a=b.col_b where b.col_b <> 5;
完整逻辑计算流程
我们按照SQL的标准语义执行顺序拆解:
第一步:执行LEFT JOIN关联
左连接的规则是保留左表(A)的所有行,右表(B)匹配a.col_a = b.col_b条件的行对应填充,匹配不到的位置补NULL,关联后得到的中间结果集为:COL_A COL_B 1 1 2 2 3 3 4 NULL 注意:B表中
col_b=5的行没有匹配的A表行,所以不会出现在左连接的中间结果中。第二步:执行WHERE子句过滤
对中间结果执行b.col_b <> 5的过滤规则:Oracle中NULL和任何值做比较运算的结果都是UNKNOWN,只有判定为TRUE的行才会被保留。因此col_b=NULL的第4行被过滤,最终得到你看到的3行结果:COL_A COL_B 1 1 2 2 3 3
关于优化器等价优化的说明
你可能会发现,如果先过滤B表中col_b=5的行,再和A做左连接,得到的结果和上面完全一致,这是Oracle优化器做的谓词下推等价优化,属于物理执行层面的调整,前提是完全不改变SQL的语义结果,不代表逻辑执行顺序变成了先执行WHERE再执行JOIN。
你可以做个简单验证:把WHERE条件改成WHERE b.col_b IS NULL,执行后会返回COL_A=4、COL_B=NULL的结果。如果逻辑上先过滤B表,B表本身没有col_b=NULL的行,关联后不可能得到这个结果,这就直接验证了逻辑层面一定是先执行LEFT JOIN再执行WHERE。
内容的提问来源于stack exchange,提问作者Rakesh Raikwar
相关产品推荐
相关产品推荐

