如何在Scala中获取DataFrame 1中存在但DataFrame 2中不存在的数据
在Scala中筛选DF1独有的数据(DF1存在但DF2不存在的记录)
你好呀!针对你要找出DF1里有但DF2里没有的数据这个需求,在Spark Scala里有几种实用的方法,我给你拆解一下:
方法1:用except算子(整行对比+自动去重)
如果你的DF1和DF2结构完全一致(列名、类型都匹配),想要找出整行在DF2中不存在的记录,except是最直接的选择,不过它会自动去重哦:
// 直接得到DF1独有的行(去重后) val df1UniqueRows = df1.except(df2) df1UniqueRows.show()
举个例子:如果DF1里有5条一模一样的行,而DF2里没有,用except返回的结果只会保留1条。
方法2:用左外连接+过滤(保留重复行,自定义关联键)
如果需要保留DF1的重复行,或者只需要根据某几个关键字段判断“是否存在”(比如你的例子里的PRS_ID),可以用左外连接后过滤null值:
// 以PRS_ID为关联键做左连接,保留DF1所有行 val leftJoinResult = df1.join(df2, Seq("PRS_ID"), "left_outer") // 过滤出DF2中没有匹配到的行(DF2的PRS_ID为null说明无匹配) val df1Only = leftJoinResult.filter(df2("PRS_ID").isNull) // 只保留DF1的原始列(可选,根据需求调整) val finalResult = df1Only.select(df1.columns.map(df1(_)): _*) finalResult.show()
这种方法的灵活性很高,你可以根据实际业务选择关联的字段,比如同时用REQ_ID和PRS_ID作为关联键,只需要把Seq("PRS_ID")改成Seq("REQ_ID", "PRS_ID")就行。
方法3:用anti join(Spark 2.1+,语义明确且高效)
这是我最推荐的方法,Spark从2.1版本开始支持anti join,专门用来解决“左表有但右表没有”的问题,不仅语义清晰,还会保留DF1的重复行,而且结果里只有DF1的列:
// 基于PRS_ID做anti join,直接得到DF1中在DF2无匹配的行 val df1Only = df1.join(df2, Seq("PRS_ID"), "anti") df1Only.show()
这个方法不需要额外处理过滤或列选择,完全贴合你的需求,效率也比左连接过滤更高。
额外提示
如果DF2里的PRS_ID是DF1中REQ_ID的前缀(比如你例子里的情况),可以先对DF1的REQ_ID做字符串截取,再和DF2的PRS_ID关联,比如:
import org.apache.spark.sql.functions.substring val df1WithShortReqId = df1.withColumn("SHORT_REQ_ID", substring($"REQ_ID", 1, 18)) val df1Only = df1WithShortReqId.join(df2, $"SHORT_REQ_ID" === df2("PRS_ID"), "anti")
内容的提问来源于stack exchange,提问作者Krishna
相关产品推荐
相关产品推荐

