我有以下代码:
SparkConf sparkConf = new SparkConf();
JavaSparkContext ctx = new JavaSparkContext(sparkConf);
HiveContext sqlContext = new HiveContext(ctx.sc());
DataFrame df1 = sqlContext.read().json("../smthng/*.json");
DataFrame df2 = sqlContext.read().json("../else/*.json");
df1.registerTempTable("df1");
df2.registerTempTable("df2");
DataFrame df= sqlContext.sql("SELECT * " +
"FROM df1 " +
"LEFT OUTER JOIN df2 ON df1.id = df2.id " +
"WHERE df1.id IS NULL").drop("df1.id");
在这里,我尝试进行外部联接,然后删除其中一个id
列。显然,联接会保留两个列,当我尝试进一步使用它时,它无法决定使用哪一个(我得到的错误如Reference 'id' is ambiguous, could be: id#59, id#376.;
)。这就是我尝试删除其中一列的原因,但即使我使用....drop("df1.id");
,它也无法正常工作。我有什么想法可以删除其中一个id
列吗?
谢谢!
答案 0 :(得分:2)
没有专栏" df1.id"在由连接查询创建的DF中,因此drop不起作用。考虑在DF之后返回查询。
+---+----+-----+----+
| id|name|email| id|
+---+----+-----+----+
| 2| xxx| null|null|
| 3| zzz| null|null|
+---+----+-----+----+
如果你打电话给df.printSchema(),你会得到
root
|-- id: integer (nullable = false)
|-- name: string (nullable = true)
|-- email: string (nullable = true)
|-- id: integer (nullable = true)
所以如果你打电话给drop(" id")。它会掉落" id"列并将返回
+----+-----+
|name|email|
+----+-----+
| xxx| null|
| zzz| null|
+----+-----+
如果你想拥有一个" id"最终DF中的列然后将您的查询更改为如下所示
DataFrame df = sqlContext.sql("SELECT df1.id, df1.name, df2.email " +
"FROM df1 " +
"LEFT OUTER JOIN df2 ON df1.id = df2.id "
+"WHERE df1.id IS NULL");
它会返回
+---+----+-----+
| id|name|email|
+---+----+-----+
| 2| xxx| null|
| 3| zzz| null|
+---+----+-----+
Spark DF API提供类似"别名"的API。或" withColumnRename"处理DF中的重复列。另请参阅帖子Spark Dataframe distinguish columns with duplicated name。
答案 1 :(得分:0)
在sql中使用列名,并使用别名 -
DataFrame df= sqlContext.sql("SELECT Column1 as col1,Column2 as col2...ColumnN as colN" +
"FROM df1 " +
"LEFT OUTER JOIN df2 ON df1.id = df2.id " +
"WHERE df1.id IS NULL").drop("df1.id");
希望这种方法不会给出像“模棱两可”这样的错误信息
答案 2 :(得分:0)
好的,我通过使用这样的连接解决了这个问题:
DataFrame df = df1.join(df2, df1.col("id").equalTo(df2.col("customer_id")), "left")
.select("*").where(df1.col("id").isNotNull())
.drop(df1.col("id"));