如何在Inner Join后保留DataFrame df1的原有格式?
Spark DataFrame内连接后保留原表列的解决方案
问题场景
我有两个DataFrame:
- df1包含列:
first_name、last_name、id、location、phone_number(实际有近30列) - df2包含列:
last_name、id、location、employer
需求是通过last_name和id做内连接,只保留两表中这两个字段都匹配的行,并且只保留df1的原有列,不要引入df2的额外列,也避免出现列名歧义。
当前用这段代码执行连接:
df1.join(df2, df1.col("last_name").equalTo(df2.col("last_name").and(df1.col("id").equalTo(df2.col("id"))), "inner");
结果不仅多出了df2的列(比如employer),id、last_name还出现了重复歧义的列。
解决办法
办法1:用关联键筛选替代完整连接(最省事)
不用做全表join,直接筛选df1中(last_name, id)存在于df2的行,直接得到df1的原格式:
// 先提取df2的连接键 val df2Keys = df2.select("last_name", "id") // 用inner join关联键,自动合并重复的连接列,直接得到df1的所有列 val result = df1.join(df2Keys, Seq("last_name", "id"), "inner")
或者用exists子查询的写法:
import org.apache.spark.sql.functions._ val result = df1.filter( exists(df2, row => row.getAs[String]("last_name") === col("last_name") && row.getAs[String]("id") === col("id") ) )
办法2:join后直接选取df1的全部列
如果一定要用原join逻辑,join完成后直接通过df1的列名集合选取所有列,不用逐个手写:
// 用Seq指定连接键,避免歧义列 val joinedDf = df1.join(df2, Seq("last_name", "id"), "inner") // 直接选取df1的所有列 val result = joinedDf.select(df1.columns.map(col): _*)
办法3:表别名+精准选取原表列
如果连接条件需要更复杂的列判断,可以给表加别名,之后直接选取别名表的所有列:
val a = df1.alias("a") val b = df2.alias("b") val result = a.join( b, a("last_name") === b("last_name") && a("id") === b("id"), "inner" ).select(a.columns.map(a(_)): _*)
内容的提问来源于stack exchange,提问作者spp
相关产品推荐
相关产品推荐

