left join比inner join更常用,因其能100%保留左表所有行,满足保全主表数据的刚性需求;而inner join仅保留两表交集,易导致用户等关键数据丢失。

因为业务分析中“保全主表数据”是刚性需求,而 LEFT JOIN 是唯一能 100% 保证左表所有行不丢失的合并方式。
LEFT JOIN 为什么比 INNER JOIN 更常用
INNER JOIN 会丢掉左表中在右表无匹配的记录,但现实中大量场景要求“一个都不能少”:比如统计全部用户行为,哪怕某用户没下单、没点击、没登录,也得出现在结果里——否则漏掉的就是潜在问题用户或数据采集异常点。
常见错误现象:pd.merge(df_user, df_order, on='user_id') 默认是 how='inner',一执行就发现用户数从 10 万掉到 2 万,不是数据变少了,是过滤掉了。
- LEFT JOIN 保留左表全部行,右表无匹配则填
NaN - INNER JOIN 只保留两表都有的键,本质是交集
- 企业报表、BI 看板、风控名单生成等场景,主表(如用户表、商品表)通常不允许丢行
how='left' 的参数必须显式写,不能依赖默认
很多人以为 pd.merge() 默认就是左连接,其实它默认是 how='inner'。不写 how 参数等于主动选择丢数据。
正确写法必须明确:pd.merge(left_df, right_df, on='id', how='left')
- 不写
how→how='inner'→ 隐形丢行 - 写
how='left'→ 左表行数 ≥ 结果行数,可验证是否真全量 - 如果右表有重复键(比如一个 user_id 对应多条订单),LEFT JOIN 会自动展开,行数可能膨胀——这是预期行为,不是 bug
ON 条件写错位置,LEFT JOIN 就变 INNER JOIN
把过滤条件误写在 WHERE 子句(即 query() 或后续布尔索引),会导致左表被二次过滤。例如:
result = pd.merge(df_user, df_order, on='user_id', how='left')
result = result.query("order_amount > 100") # 错!这里会把 order_amount 为 NaN 的行(即无订单用户)全干掉
真正想保留无订单用户、只筛有订单且金额 >100 的,得把条件塞进右表预处理,或用 indicator=True 辅助判断来源。
- LEFT JOIN 的语义只在
merge这一步生效 - 后续任何
query、loc、boolean indexing都是全局过滤,不管 NaN - 需要“左表全量 + 右表部分满足条件”时,优先对右表先
query再 merge
容易被忽略的 NULL 处理和性能影响
LEFT JOIN 后右表字段带 NaN 是常态,但很多人直接拿去算均值、求和、分组,结果悄无声息地变小或报错。
比如:result['order_amount'].sum() 默认跳过 NaN,但 result.groupby('city')['order_amount'].mean() 也会跳过——如果你本意是“每个城市人均订单额”,那没问题;但如果是“每个城市总销售额 / 总用户数”,就得先用 fillna(0) 补零再算。
-
NaN在数值计算中默认被忽略,但逻辑判断(如==)永远返回False - 大表 LEFT JOIN 时,右表若未对
on字段建索引,merge会变慢;pandas 内部不建索引,靠哈希,所以键列类型要一致(比如都是int64,别混object) - 合并后立刻检查
result['right_col'].isna().sum(),能快速确认右表匹配率,比看行数更靠谱
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











