Apache Spark关联键含空值时如何正确Join获取两边全量字段数据
根因说明
Spark 默认的等值匹配逻辑中,null 和 null 的判定结果为不相等,因此你用包含空值的字段作为关联键时,两边相同的空键不会被识别为匹配项,才会出现左连接取不到name、右连接取不到id、全连接拆分为4条记录的问题。
解决方案
有两种常用实现方式,均可满足空值关联匹配的需求:
方案1:使用空安全相等运算符写关联条件
Spark 提供的 <=> 是空安全相等运算符,当两边值相等或两边均为null时会返回true,刚好匹配你的需求,代码如下:
import org.apache.spark.sql.functions.col // 先重命名df1的id字段 val df1WithRename = df1.withColumnRenamed("id", "tally_summary_id") // 手动定义关联条件,所有键都用空安全相等 val joinCondition = df1WithRename("tally_number") <=> df2("tally_number") && df1WithRename("work_order_number") <=> df2("work_order_number") && df1WithRename("work_order_item_number") <=> df2("work_order_item_number") && df1WithRename("company_code") <=> df2("company_code") // 左连接即可,不需要全连接 val finalDf = df1WithRename.join(df2, joinCondition, "left") // 选取需要的输出字段,避免重复列 .select( df1WithRename("tally_number"), df1WithRename("work_order_number"), df1WithRename("work_order_item_number"), df1WithRename("company_code"), col("tally_summary_id"), col("name") )
方案2:空值填充后再关联
如果你的业务场景中这两个字段的空值没有特殊含义,可以先把两边关联键的空值统一填充为同一个占位值(比如空字符串),再用常规的等值关联即可:
// 需要填充空值的关联键列表 val fillColumns = Seq("work_order_number", "work_order_item_number") val fillValue = "" // 两边分别处理空值,同时重命名df1的id val df1Processed = df1 .withColumnRenamed("id", "tally_summary_id") .na.fill(fillValue, fillColumns) val df2Processed = df2.na.fill(fillValue, fillColumns) // 常规等值关联即可 val finalDf = df1Processed.join( df2Processed, Seq("tally_number", "work_order_number", "work_order_item_number", "company_code"), "left" )
两种方案执行后的输出结果均和你期望的一致。
内容的提问来源于stack exchange,提问作者Arij SEDIRI
相关产品推荐
相关产品推荐

