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

Redshift中LEFT JOIN两种条件写法的执行差异解析及疑问:WHERE子句后置vs ON子句附加条件

Redshift中LEFT JOIN两种条件写法的差异解析

咱们直接把这两种写法的核心差异和你的理解误区掰明白:

一、两种写法的逻辑本质完全不同

1. 写法一:WHERE子句过滤主表(table1)

explain select * from table1 t left join table2 t2 on t.key = t2.key where t.snapshot_day = to_date('2021-12-18', 'YYYY-MM-DD');

逻辑行为:
先从table1里筛出所有snapshot_day = '2021-12-18'的行,再把这些筛选后的行和table2做LEFT JOIN——也就是说,最终结果里只会保留table1中符合日期条件的行,匹配不到table2的行则table2字段为NULL。

执行计划验证:
你看执行计划里table1的Seq Scan带了Filter,只返回了287万多行,之后做哈希的成本极低,最终返回行数和主表筛选后的行数基本一致,这就是优化器做了谓词下推——把WHERE里的主表过滤提前到JOIN之前执行,减少了后续JOIN的数据量。

2. 写法二:ON子句附加主表条件

explain select * from table1 t left join table2 t2 on t.key= t2.key and t.snapshot_day = to_date('2021-12-18', 'YYYY-MM-DD');

逻辑行为:
保留table1的所有行,然后对table1的每一行,只有当该行的snapshot_day = '2021-12-18'时,才会去匹配table2中key相等的行;如果table1的行日期不符合,哪怕key能匹配table2,table2的字段也会是NULL。简单说,这个条件是用来限制右表匹配的规则,而不是过滤左表。

执行计划验证:
执行计划里table1的Seq Scan没有Filter,扫描了全部32亿多行,哈希表的成本直接拉满,最终返回行数和table1总行数一致——这就是因为左表没有被过滤,所有行都保留了。

二、你的理解误区在哪里?

  1. 误区一:WHERE子句一定在JOIN之后执行
    其实对于LEFT JOIN的左表,优化器会自动判断:如果WHERE里的条件只涉及左表,那么可以安全地把过滤逻辑提前到JOIN之前(谓词下推),这不会改变查询结果,还能大幅减少数据处理量。你的执行计划已经证明了这一点。

  2. 误区二:ON子句中的主表条件会过滤主表
    LEFT JOIN的核心是保留左表所有行,ON子句的条件只是用来决定右表哪些行能和左表行匹配,完全不会过滤左表本身。只有INNER JOIN的ON条件才会同时过滤左右表,LEFT JOIN的ON条件对左表没有过滤作用。

三、总结建议

  • 如果需要过滤左表的行(只保留符合条件的左表行再关联),一定要用WHERE子句写左表的过滤条件;
  • 如果是想保留左表所有行,但仅当左表行符合某条件时才去匹配右表,才用ON子句附加左表条件——这种场景其实很少见,大部分时候你需要的是第一种写法。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 06:56:03